Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 2 [3] 4 5 ... 8

Author Topic: Holidays  (Read 9227 times)

Roses

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #30 on: September 24, 2019, 08:54:42 am »

Answers in quote

Well, if you want sometime to happen on a specific day of the year, you just need to convert that day into the correct tick, with 1200*28*12 ticks in a year. So if you wanted a script to run on 0315 thats 1200*(2*28+15). Then you just set up a timeout callback using dfhack.timeout. It should look something like this;

Code: [Select]
year_ticks = 1200*28*12
current_tick = df.global.cur_year_tick
holiday_tick = 1200*(2*28+15)
ticks = holiday_tick - current_tick
if ticks < 0 then
 ticks = ticks + year_ticks
end
dfhack.timeout(ticks+1,'ticks',holiday_function)

That way every time you start up the game it will calculate how many ticks are between that particular time and when the holiday script should be run and sets up a timeout that will run at that number of ticks. Then you just need to make sure that the holiday function sets up the next timeout so that if someone plays for more than a year of in game time in one sitting they don't miss any of the holiday changes.

Awesome thanks.

So I'm trying to digest this.

I assume that the following are all new custom variables that we are creating in the lua file. Do they need to be defined first as int or is that not needed in lua?
Not needed in lua, the only declarations for variables in lua are local and global. By default everything is global. So it's good practice to say local year_ticks = 1200*28*12 if you are only going to use it locally.

Code: [Select]
year_ticks = 1200*28*12
current_tick = df.global.cur_year_tick
holiday_tick = 1200*(2*28+15)
ticks = holiday_tick - current_tick

Is the following a function that dfhack already knows? Does it return the current year tick? Is there a list of these and what they do somewhere?
It's not a function but a variable in DF that DFHack can read. https://github.com/DFHack/df-structures has the full list of variables accessible, not all of which have been identified. There is a LOT of information in that link, and I am usually all for self discovery and such, but if you have specific things you are looking for it may be easiest to either send someone a PM, ask in the DFHack thread, or ask on the DFHack IRC channel

Code: [Select]
df.global.cur_year_tick
If that's true, couldnt the if statement just be:
The problem with this is you would need to run the script every tick, which depending on what the script does can cause slow down, and also is not needed

Code: [Select]
if current_tick == holiday_tick then
 [do something]
end

Is the following another pre-defined dfhack function? I assume that this stops the script and returns a variable for use elsewhere? Is the holiday_function the variable/value that is being returned from this script?
Now this is a dfhack function available in lua (a full list can be found at https://dfhack.readthedocs.io/en/stable/docs/Lua%20API.html). What this tells the game is, after ticks+1 amount of time, run the holiday_function, where holiday_function should be replaced with what you want to happen for that holiday.

Code: [Select]
dfhack.timeout(ticks+1,'ticks',holiday_function)
How does this script return back to the init file to run a command off of that date?
As written it doesn't. I could write you up a full script, but I'm going to put on my teacher hat and let you try to write it on your own, then I can answer questions as needed.

I'll watch a youtube video on some basic lua syntax to get a better understanding of how to read the code.
Logged

brolol.404

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #31 on: September 24, 2019, 11:09:45 am »

Alright. I'm going to take a stab at this.
I decided that I am going to start with something simple and I decided to pick a holiday close to embark for easy testing.

So, the first holiday will be on Granite 17 (2 days after embark). On that day, a leprechaun will spawn somewhere on the map and stick around for a few days (maybe a week). He will be very fast with FLEEQUICK and NOEXERT (or at least very high endurance). He will be made of a really weak material (like salt) so one hit will kill him. He will leave behind no corpse, but instead a bunch of gold coins (ITEMCORPSE with masterpiece ITEMCORPSE_QUALITY). Let's see if I can make this happen.
« Last Edit: September 24, 2019, 11:33:51 am by brolol.404 »
Logged

Roses

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #32 on: September 24, 2019, 11:46:51 am »

Sounds like a good starting point
Logged

Meph

  • Bay Watcher
    • View Profile
    • worldbicyclist
Re: Holidays
« Reply #33 on: September 24, 2019, 12:45:04 pm »

Spawn "somewhere" might be the trickiest part. Because you need to figure out which places are solid rock, open space, and which are floor that allows creatures to be spawned on; without pummeling to their death/drowning/encased/burninginmagma. ^^
Logged
::: ☼Meph Tileset☼☼Map Tileset☼- 32x graphic sets with TWBT :::
::: ☼MASTERWORK DF☼ - A comprehensive mod pack now on Patreon - 250.000+ downloads and counting :::
::: WorldBicyclist.com - Follow my bike tours around the world - 148 countries visited :::

brolol.404

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #34 on: September 24, 2019, 01:55:31 pm »

Spawn "somewhere" might be the trickiest part. Because you need to figure out which places are solid rock, open space, and which are floor that allows creatures to be spawned on; without pummeling to their death/drowning/encased/burninginmagma. ^^

How would you handle this? Spawn it at the highest z level and make it immune to damage for a few ticks?

How do wild animals spawn? Is there pre-written code for them?

Roses

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #35 on: September 24, 2019, 02:03:45 pm »

Spawn "somewhere" might be the trickiest part. Because you need to figure out which places are solid rock, open space, and which are floor that allows creatures to be spawned on; without pummeling to their death/drowning/encased/burninginmagma. ^^

How would you handle this? Spawn it at the highest z level and make it immune to damage for a few ticks?

How do wild animals spawn? Is there pre-written code for them?

Something like

Code: [Select]
function getPositionSurface()
 local rand = dfhack.random.new()
 local mapx, mapy, mapz = dfhack.maps.getTileSize()
 randx = rand:random(mapx)
 randy = rand:random(mapy)
 local pos = {}
 pos.x = randx
 pos.y = randy
 pos.z = mapz - 1
 local j = 0
 while dfhack.maps.ensureTileBlock(pos.x,pos.y,pos.z-j).designation[pos.x%16][pos.y%16].outside do
  j = j + 1
 end
 pos.z = pos.z - j + 1
 return pos
end

Gets a random x and y, then finds the surface at that x and y coordinate starting from the top of the map and working down. Not the most efficient way to do it, but it works.

EDIT: Also doesn't check if there's magma or deep water or anything like that. But you can check the designation and occupancy for those things
« Last Edit: September 24, 2019, 02:07:53 pm by Roses »
Logged

brolol.404

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #36 on: September 24, 2019, 05:18:57 pm »

Thanks. Can I put this in the middle of a lua script or do these modtools commands only work in an init file?

Code: [Select]
[ modtools/create-unit -race GOBLIN -caste MALE -name EVIL -location pos -age 13 ]

Roses

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #37 on: September 24, 2019, 05:59:47 pm »

You would need to do a dfhack.run_script("modtools/create-unit ...")
Logged

brolol.404

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #38 on: September 24, 2019, 08:52:52 pm »

I get that this pulls from the current time, but what is actually returned? Is this in milliseconds? It it a number 1 - 59?
local rand = dfhack.random.new()
What do the following lines do? Is this running a rand:random function using the local mapx variable and then putting the returned value into the randx variable? What does the colon do? Why isn't this a local variable?
randx = rand:random(mapx)
 randy = rand:random(mapy)
The function returns pos, but it doesn't look like the pos variable was ever updated after it's initial definition. What is the pos variable being defined as with {}?

I don't see this function listed in the DFHack Lua API docs? What does this mean exactly? What are the %?
 
dfhack.maps.ensureTileBlock(pos.x,pos.y,pos.z-j).designation[pos.x%16][pos.y%16].outside

edit: I realized that I don't know how to target the created unit and destroy it or make it leave the map after 1200*5 ticks.
« Last Edit: September 25, 2019, 06:41:50 am by brolol.404 »
Logged

brolol.404

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #39 on: September 25, 2019, 06:51:17 am »

How does this look? Do functions need their own lua files or can they be in the same lua file as the rest of the script?

holiday_shamrock.lua
Code: [Select]
holiday_shamrock_countdown()

function holiday_shamrock_countdown()
local year_tick_total = 1200*28*12
local current_tick = df.global.cur_year_tick
local date_shamrock = 1200*(2*28+17)
local ticks = date_shamrock - current_tick
if ticks < 0 then
 ticks = ticks + year_tick_total
end
dfhack.timeout(ticks+1,'ticks',holiday_shamrock(ticks))

function holiday_shamrock(ticks)
getPositionSurface()
dfhack.run_script(modtools/create-unit -race holiday_LEPRECHAUN -caste MALE -name PLAINS -location pos -age 1)
dfhack.timeout(ticks+1,'ticks',holiday_shamrock_countdown)
end

function getPositionSurface()
 local rand = dfhack.random.new()
 local mapx, mapy, mapz = dfhack.maps.getTileSize()
 randx = rand:random(mapx)
 randy = rand:random(mapy)
 local pos = {}
 pos.x = randx
 pos.y = randy
 pos.z = mapz - 1
 local j = 0
 while dfhack.maps.ensureTileBlock(pos.x,pos.y,pos.z-j).designation[pos.x%16][pos.y%16].outside do
  j = j + 1
 end
 pos.z = pos.z - j + 1
 return pos
end

EDIT:

I assume the following would go in OnMapLoad.init?

Code: [Select]
dfhack.run_script(holiday_shamrock.lua)
« Last Edit: September 25, 2019, 07:17:47 am by brolol.404 »
Logged

brolol.404

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #40 on: September 25, 2019, 07:59:52 am »

Instead of coding the leprechaun to leave the map, I could give it [MISCHIEVIOUS] and [CURIOUSBEAST_ITEM], so it will start invisible, try to steal an item and then leave the map on it's own.

Roses

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #41 on: September 25, 2019, 10:06:09 am »

How does this look? Do functions need their own lua files or can they be in the same lua file as the rest of the script?

holiday_shamrock.lua

holiday_shamrock_countdown()

function holiday_shamrock_countdown()
 local year_tick_total = 1200*28*12
 local current_tick = df.global.cur_year_tick
 local date_shamrock = 1200*(2*28+17)
 local ticks = date_shamrock - current_tick
 if ticks < 0 then
  ticks = ticks + year_tick_total
 end
 dfhack.timeout(ticks+1,'ticks',function () holiday_shamrock(ticks) end)
end

function holiday_shamrock(ticks)
 pos = getPositionSurface()
 dfhack.run_script(modtools/create-unit -race holiday_LEPRECHAUN -caste MALE -name PLAINS -location pos -age 1)
 dfhack.run_script("modtools/create-unit","-race","holiday_LEPRECHAUN","-caste","MALE","-name","PLAINS","-location",pos,"-age",1)
 dfhack.timeout(ticks+1,'ticks',holiday_shamrock_countdown)
 holiday_shamrock_countdown()
end

function getPositionSurface()
 local rand = dfhack.random.new()
 local mapx, mapy, mapz = dfhack.maps.getTileSize()
 randx = rand:random(mapx)
 randy = rand:random(mapy)
 local pos = {}
 pos.x = randx
 pos.y = randy
 pos.z = mapz - 1
 local j = 0
 while dfhack.maps.ensureTileBlock(pos.x,pos.y,pos.z-j).designation[pos.x%16][pos.y%16].outside do
  j = j + 1
 end
 pos.z = pos.z - j + 1
 return pos
end


EDIT:

I assume the following would go in OnMapLoad.init?

Code: [Select]
dfhack.run_script(holiday_shamrock.lua)

Modified code in post, a couple comments;
1. The function call in the timeout has a specific format in that it can't take input variables. To get around this we create a sudo function whose only purpose is to call the function you want.
2. The function getPositionSurface returns a table with x, y, z values. When you call it you have to assign that table to a variable. Without the 'pos =' part your holiday_shamrock function wouldn't know what the variable pos means.
3. dfhack.run_script takes its input as a set, not as a whole. So you need to seperate them out with commas
4. Unless you are passing a variable you need to use quotes (single or double) to identify what you are passing as a string. As you can see, everything in the dfhack.run_script call it a string except for pos which is a variable (and the 1)
5. It isn't necessary to do another timeout call in the holiday_shamrock function, you can just straight call the holiday_shamrock_countdown() function and it will set up another call back itself

The OnMapLoad.init shouldn't need the dfhack.run_script part (in fact it might not even know what dfhack is) you should just be able to put
Code: [Select]
holiday_shamrockno .lua needed. It will then run the file
Logged

brolol.404

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #42 on: September 25, 2019, 12:23:02 pm »

How does the script know to populate the local pos = {} table with pos.x, pos.y and pos.z? It doesn't look like anything is assigned to pos after it's initial definition?
2. The function getPositionSurface returns a table with x, y, z values.
Is there a difference between single and double quotes?
4. Unless you are passing a variable you need to use quotes (single or double) to identify what you are passing as a string.

Thanks for all the help :)

Unfortuanely, I just tested it out and nothing seems to happen. Is there a way to debug where the issue could be (like an errorlog for dfhack)?

\raw\OnMapLoad.init

Code: [Select]
holiday_shamrock
\hack\scripts\holiday_shamrock.lua

Code: [Select]
holiday_shamrock_countdown()

function holiday_shamrock_countdown()
 local year_tick_total = 1200*28*12
 local current_tick = df.global.cur_year_tick
 local date_shamrock = 1200*(2*28+17)
 local ticks = date_shamrock - current_tick
 if ticks < 0 then
  ticks = ticks + year_tick_total
 end
 dfhack.timeout(ticks+1,'ticks',function () holiday_shamrock(ticks) end)
end

function holiday_shamrock(ticks)
 pos = getPositionSurface()
 dfhack.run_script("modtools/create-unit","-race","holiday_LEPRECHAUN","-caste","MALE","-name","PLAINS","-location",pos,"-age",1)
 holiday_shamrock_countdown()
end

function getPositionSurface()
 local rand = dfhack.random.new()
 local mapx, mapy, mapz = dfhack.maps.getTileSize()
 randx = rand:random(mapx)
 randy = rand:random(mapy)
 local pos = {}
 pos.x = randx
 pos.y = randy
 pos.z = mapz - 1
 local j = 0
 while dfhack.maps.ensureTileBlock(pos.x,pos.y,pos.z-j).designation[pos.x%16][pos.y%16].outside do
  j = j + 1
 end
 pos.z = pos.z - j + 1
 return pos
end

\raw\objects\creature_holiday.txt

Code: [Select]
creature_holiday

[OBJECT:CREATURE]

[CREATURE:holiday_LEPRECHAUN]
[DESCRIPTION:A small humanoid creature.]
[NAME:leprechaun:leprechauns:leprechaun]
[CASTE_NAME:leprechaun:leprechauns:leprechaun]
[CREATURE_TILE:'l'][COLOR:2:0:1]
[PREFSTRING:mythical tales of gold]

[FANCIFUL]
DOES_NOT_EXIST
MISCHIEVIOUS
CURIOUSBEAST_ITEM
[FLEEQUICK]
[TRAPAVOID]
[CANOPENDOORS]
[NOEXERT][NOPAIN]
[ITEMCORPSE:COIN:NO_SUBTYPE:INORGANIC:GOLD]
[ITEMCORPSE_QUALITY:5]
[NOSTUN][NONAUSEA][NO_DIZZINESS][NO_FEVERS]
[NO_DRINK][NO_EAT][NO_SLEEP]
[BENIGN]
[INTELLIGENT]
[ODOR_LEVEL:0]
[GRASSTRAMPLE:0]

[NATURAL_SKILL:SNEAK:8]
[NATURAL_SKILL:SWIMMING:6]
[NATURAL_SKILL:SITUATIONAL_AWARENESS:8]
[NATURAL_SKILL:DODGING:8]
[NATURAL_SKILL:CLIMBING:6]

[PHYS_ATT_RANGE:STRENGTH:0:400:600:750:800:900:1100]                    --
[PHYS_ATT_RANGE:AGILITY:700:1200:1400:1500:1600:1800:2500]              ++
[PHYS_ATT_RANGE:TOUGHNESS:0:400:600:750:800:900:1100]                   --
[MENT_ATT_RANGE:INTUITION:450:950:1150:1250:1350:1550:2250]             +
[MENT_ATT_RANGE:MEMORY:5000:5000:5000:5000:5000:5000:5000]              max
[MENT_ATT_RANGE:SPATIAL_SENSE:700:1200:1400:1500:1600:1800:2500]        ++
[MENT_ATT_RANGE:KINESTHETIC_SENSE:700:1200:1400:1500:1600:1800:2500]    ++

[NOBONES][NOBREATHE][EXTRAVISION]
[BODY:BASIC_1PARTBODY]
[NO_THOUGHT_CENTER_FOR_MOVEMENT]
[TISSUE:SALT]
[TISSUE_NAME:magic:magic]
[TISSUE_MATERIAL:INORGANIC:SALT]
[MUSCULAR]
[FUNCTIONAL]
[STRUCTURAL]
[RELATIVE_THICKNESS:1]
[CONNECTS]
[TISSUE_SHAPE:LAYER]
[TISSUE_LAYER:BY_CATEGORY:ALL:SALT]

[BODY_SIZE:0:0:15000]
[BODY_APPEARANCE_MODIFIER:HEIGHT:90:95:98:100:102:105:110]
[BODY_APPEARANCE_MODIFIER:BROADNESS:90:95:98:100:102:105:110]
[MAXAGE:230:250]
[DIURNAL]
[HOMEOTHERM:10067]

[APPLY_CREATURE_VARIATION:STANDARD_BIPED_GAITS:900:447:298:145:1900:2900] 60 kph
[APPLY_CREATURE_VARIATION:STANDARD_CLIMBING_GAITS:2206:1692:1178:585:3400:4900] 15 kph
[APPLY_CREATURE_VARIATION:STANDARD_SWIMMING_GAITS:2990:2257:1525:731:4300:6100] 12 kph
[SWIMS_INNATE]

[CASTE:MALE]
[MALE]

Roses

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #43 on: September 25, 2019, 01:25:53 pm »

1) local pos = {}       <- defines the name variable as a table
    pos.x = randx       <- assigns the variable x in table pos as randx

2) No difference in practical terms

3) What happens if you just run holiday_shamrock on the DFHack command line. You can also put print statements in the script in order to see if it is doing anything, or completely failing.
 
Logged

brolol.404

  • Bay Watcher
    • View Profile
Re: Holidays
« Reply #44 on: September 25, 2019, 03:10:02 pm »

Could this be added to function holiday_shamrock(ticks) to display a holiday announcement:

Code: [Select]
dfhack.gui.showAnnouncement("SHAMROCK, GRANITE 17", "WHITE")
3) What happens if you just run holiday_shamrock on the DFHack command line. You can also put print statements in the script in order to see if it is doing anything, or completely failing.

Is this the code to add statements?

Code: [Select]
print("test")
After embark, I ran the holiday_shamrock. It returned the below and still nothing seemed to happen on the 17th.

[DFHack]# holiday_shamrock
...a\Desktop\df_44_12_win/hack/scripts/holiday_shamrock.lua:1: attempt to call a nil value (global 'holiday_shamrock_countdown')
stack traceback:
        ...a\Desktop\df_44_12_win/hack/scripts/holiday_shamrock.lua:1: in local 'script_code'
        C:\Users\bro\Desktop\df_44_12_win\hack\lua\dfhack.lua:680: in function 'dfhack.run_script_with_env'
        (...tail calls...)
Pages: 1 2 [3] 4 5 ... 8