Scripting questions

"eventually EUO will get to the point its (sic) unplayable" - Dudle

Moderator: EUO Moderators

Post Reply
mud
I once posted in TFIOOC!
Posts: 134
Joined: Wed Nov 09, 2005 12:29 pm

Scripting questions

Post by mud » Wed Sep 01, 2010 11:58 am

So, Lua seems easy enough, and I've tried to glean what I can from old scripting threads, the manual, and the Lua bindings egg posted in the maped thread, but I still have quite a few questions. Anyone want to help me out?

I apologize if any of these are answered elsewhere. I have looked, but it's always possible I missed something.
  1. Can my scripts save state:
    1. As global variables, between scripting calls? Or is all of that gone every time a new script function is called? Is the global context reset whenever a map unloads, or the server resets, or anything like that? What about the actual state of the map, such as tiles which have been changed in a script?
    2. In a file?
    3. In a MySQL table? I see a function for MySQL queries in the Lua exports, but can I use it?
    4. Associated with a character somehow? (what form can this take?)
  2. Can I somehow iterate over the players:
    1. On a map?
    2. In an area?
    3. Currently online?
  3. Can I do the same for mobs? It seems like I could call Monsters:get_by_xyz(...) for every x and y on a map or an area, but is there a better way?
  4. In general, are ids unique or reused? If I for some reason store the id of a player and later check, will that always refer to the same player or could it be someone else? Same answer for mob ids and etc.?
  5. In this post: viewtopic.php?f=11&t=2657#p41518, I see a few functions with hardcoded names which are called in certain situtations, eat_food() for example. Can I hook into those, or can only one such function exist? For example, can I do something along the lines of this in my map load function?:

    Code: Select all

    function mud_eat_food()
       server_message("Someone is getting fat")
       if mud_old_eat_food then
          return mud_old_eat_food()
       end
    end
    
    function load_map_999()
       mud_old_eat_food = eat_food
       eat_food = mud_eat_food
    end
    
    Sorry if I mucked up the syntax (still not a master of Lua of course), hopefully the intent is clear though.
  6. Can I create instance maps, and/or create a map from scratch with scripts? Would that be what load_temp_map is for, or is that specifically for treasure caverns or something like that?
  7. Can conversations use scripts? Like, can I have the response from an NPC for a keyword be generated in Lua? (and have other side effects?)
  8. Can mapmakers do quests themselves? I see some of the functions for it in the Lua exports file and mentioned elsewhere, but it's not entirely clear how that works. I'd certainly be interested in learning if possible, because I'd like to get creative with quests if I can.
  9. Is there a way that I could get copies of a bunch of samples of what's already done? That would really help a lot. I've found a couple in the maped thread, and the old "the scripting thread", but more would be very welcome.
  10. I'd like to create a map with a lot of little puzzles, games and even competitions (like timed finishing of certain challenges, etc.) Is there a limit to how far you'd like people to go with that, or as long as it's cool and fits the game is it okay? I know you like ideas for people to do instead of grinding, so I think I could throw some interesting crap in. Some would be for quests, some would probably be thinly veiled grinding, some just for kicks.
If what I'm asking isn't clear, I'd be happy to elaborate. Thanks for any help.

User avatar
eggmceye
hello
Posts: 10370
Joined: Mon Mar 11, 2002 3:55 pm
Location: Sydney, Australia
Contact:

Re: Scripting questions

Post by eggmceye » Wed Sep 01, 2010 12:39 pm

well there is a lot there to answer, and it's kinda more productive to just help with what you need first - so what I'll do is answer it all really quickly but there may not be a lot of content in the answers

1a) yes, create a global and it doesn't get reset unless server resets or lua is reloaded- changed map tiles are saved instantly to map files, so are items
1b) yes, that is how hearthstones work - vars saved offline
1c) not atm - lua/mysql support in euo is slim but its valid req
1d) see 1b - its kinda slim and ugly atm - depends what u need, on case by case basis

2 - yes yes and yes

3 - yes but doing in the most efficient way case by case basis

4 - re used - all handled by id Class (can't remember the object)

5 - there are a bunch of funcs in lua that have i guess 'reserved names' - there is no definitive list of them. eg 'chest_loot()' - can you use them? technically yes but probably not as these are written for the server to use.
There are some like load_map_DDD() that are called by server for custom map loadup scripts - also stuff like automatic npc init scripts - can't remember the naming format

6 - yes load_temp_map is for that - instances are bit different but same principle - haven't done any lua instancing, but definitely have done lua tmp maps - eg estorraths anomaly
you can make maps from scratch! see farimond dungeon, lava caves, sg tower

7 - yes - keywords can run scripts - also i think entire npcs can be spawned with conversations w/o using the server dat files

8 - yes but its poorly documented. you dont need scripting to do quests - but scripting cna greatly enhance quests. all deps on what you need

9 - depending on your enthusiasm (which looks good) you can get pretty much everything you need - if I like you XD

10 - you should do whatever you want - the better it is and the more you do the more I will help. Also if something can't be done, I can mod the engine to make it work. I'm generally low on ideas by I can make stuff happen if someone needs it.

mud
I once posted in TFIOOC!
Posts: 134
Joined: Wed Nov 09, 2005 12:29 pm

Re: Scripting questions

Post by mud » Wed Sep 01, 2010 1:02 pm

Excellent, thanks. That should be enough to get me started, mostly trying to figure out what is possible to begin with, sounds like pretty much everything I'd want :).

I guess I'll start with the things I already (sort of) know how to do and go from there.

User avatar
hellslave
I used to bake rockcakes in my bakery.
Posts: 162
Joined: Sun Jun 20, 2004 9:40 pm

Re: Scripting questions

Post by hellslave » Fri Sep 03, 2010 11:45 pm

Having had a chat with Rusty we both seem to have started off the same way - by writing mega-bosses. I've still to really attempt any sort of map scripts (like deja vu/lost jungle) but taking even the evil slime code Rusty posted up you should be able to tweak things to make them pretty interesting. I can send you the mega-boss I've written (and has been confirmed to work) if you'd like, if so I can document most of it so it's easier for you to see what's going on
A balanced diet is a cookie in each hand :jam:

mud
I once posted in TFIOOC!
Posts: 134
Joined: Wed Nov 09, 2005 12:29 pm

Re: Scripting questions

Post by mud » Sat Sep 04, 2010 6:36 pm

Yeah, sure. I'd love to see it.

I'll PM you my email, in case you don't want to share with the world for some reason.

I've got a couple of small beginner scripts I'm working on too, in between maped work. Hopefully I'll be posting them this weekend.

User avatar
hellslave
I used to bake rockcakes in my bakery.
Posts: 162
Joined: Sun Jun 20, 2004 9:40 pm

Re: Scripting questions

Post by hellslave » Sun Sep 05, 2010 2:58 pm

well, since you weren't too fussed about it being documented and since i'm a lazy ass i'll post it here and periodically edit in comments :) - Done!
This script DRASTICALLY needs nerfed (seeing it in action as it is just now could slaughter the top 20 players in about 5-10 seconds. Both damage and hp need reduced before it'll be in a playable state (just now its like 2x dragoon warrior where they need to be killed within a minute of each other))
-- = comment (just in case you couldn't guess X-D )

Code: Select all

-- event_mobs_yinyang_dragons.lua
-- by Stewart Armstrong, 13/08/10

-- YIN-YANG DRAGONS

gYinDead=0 -- Global boolean variable, 0 = false, 1 = true used to signify if the fire dragon is dead
gYangDead=0 -- As above but for the ice dragon
gTimer=0 -- does as it says on the tin, use it as a timer

function yinyang_event_init(m) -- starts the event

yin_init(m) -- set up the fire dragon
mc=spawn_near_id(0x2ae,m.id) -- spawn the ice dragon
yang_init(mc) -- set the stats on the ice dragon

end -- end of function


function yin_init(m)

	gTimer=0 -- reset the timer
	gYinDead=0 -- just spawned the dragon so its obviously not dead
	m:unlearn_spells() -- make it forget all spells
	m:learn_spell("ifh") -- teach it flame wind
	m:learn_spell("vf") -- teach it fireball
	m:set_magic_resistance(4000) -- sets MR to 4000
	m:set_name("Yin") -- Sets fire drags name
	m:set_align(ALIGN_EVIL) -- Makes it evil
	m:set_hp_max(60000) -- gives 60k hp (too much when theres 2 drags)
	m:set_intel(5000) -- Gives it 5k int
	m.mana = 300 -- sets mana to 300 (making IJO pretty useless!)
	m:set_dmg_dice(100) -- melee damage is 100d????
	m:set_dmg_sides(3) -- melee damage is 100d3 (100-300 damage per hit)
	m:set_thaco(300) -- sets AS to 300 (don't want anyones defense to break it)
	m:set_base_ac(40) -- sets it def to 40 (make it tough for people to hit it without a good weapon)
	

	m.immune_to_glassing=true -- self explanatory
	m.death_func="yin_dies" -- this function is run when the dragon is killed
	m.heartbeat_func="yin_actions" -- heartbeat function, run every second (on top of the base ai so targetting and stuff is all handled)

end -- end fire drag initialising

function yin_dies(m) -- start of death function

	local_msg(m,"Yin's flames burn out") -- sends this message out to everyone locally
	gYinDead=1 -- sets our global variable to say the fire dragon is dead
  if(gYangDead==1) then -- if the ice dragon has already been killed when we kill the fire drag
	--m.xp_kill=500000 -- commented out because it's currently breaking things for some reason
	x=math.random(1,10) -- pick a number from 1-10 inclusive to pick a weapon


	if(x==1) then wep=0x713015     -- Copper Claymore +7 breakdown = 7, the + on the weapon, 1, it's of slaying, 3, copper tint, 015, code for claymore
	elseif(x==2) then wep=0x71303c -- Copper +7 labrys
	elseif(x==3) then wep=0x7114019 -- Zinc (barbed?) +7 morning star
	elseif(x==4) then wep=0x71b018 -- Vampy +7 staff
	elseif(x==5) then wep=0x719029 -- Diamond +7 crossbow
	elseif(x==6) then wep=0x71c01b -- BR +7 dagger
	elseif(x==7) then wep=0x71e03a -- addy +7 katar
	elseif(x==8) then wep=0x81d15a -- glass +8 hoe
	elseif(x==9) then wep=0x81602a -- silver +8 great maul
	elseif(x==10) then wep=0x91703e --gold +9 rondel - deliberately retarded weapon because its a +9 
	end -- end switch case for weapon choosing
	local_msg(m,wep) -- temp debug, should be removed (checking wep had actually been initialised)
	wep=set_as_unidentified(wep) -- set it unidentified
	map:add_item(m.x,m.y,1,wep,true) -- add it to the map
	wep=set_as_unidentified(wep) -- set it unidentified again (i'm not sure why but one of the sample scripts had this, most likely only 1 is needed, not sure if it matters which, kept it in just to avoid having something extra to possibly debug, when I get time will be checked)
	update_everyones_fov(m) -- make sure everyone can see the dropped weapon
	local_msg(m, "Yin and Yang have been banished from this land!") -- Message to signal the event has ended
  end  -- end the if for checking the ice drag is dead

end -- end the fire drag death function
	
function yin_actions(m) -- the fire drags heartbeat function

if(gYangDead==1 and gTimer < 60) then  -- if the ice dragon is dead and the timer is at under 60 seconds
	gTimer = gTimer + 1 -- add a second to the timer
end

if(gYangDead==1 and gTimer>=60) then -- if the ice drag is dead and the timer is at least at 1 minute (could be == but >= does a bit more error protection)
	local_msg(m,"Yang materialises again") -- Send the message to signify the fire drag has been reborn
	mc=spawn_near_id(0x2ae,m.id) -- spawns a fire dragon
	yang_init(mc) -- sets the spawned fire dragon up like the initial one
end


m:set_health(HN_WOUNDED,0) -- bleed-proof
m:set_health(HN_HEXED,0) -- XJ-proof
m:set_health(HN_HELD,0) -- AEP-proof

if int_rand(25)==1 and m.target_id>=0 then -- on average every 25 seconds
	ptr = get_sent_ptr(m.target_id) -- get the target of the dragon
	sx=m.x-6 -- startX value for an area damage spell is 6 squares to the left of the dragon
	ex=m.x+6 -- endX is 6 squares to the right of the dragon
	sy=m.y-6 -- startY is 6 squares above the dragon
	ey=m.y+6 -- endY is 6 squares below the dragon

	local_msg(m,"Yin launches a tirade of fireballs at his attackers!")

		for xx=sx, ex do -- for every x value from sx to ex
			for yy=sy, ey do -- for every y value from sy to ey, basically first for loop does a row, second one repeats that row for every row required
	
				ptr=get_sent_ptr_xyz(xx,yy,m.map_level) -- get a reference to that individual square
				if((xx~= m.x or yy~=m.y) and ptr~=nil and ptr:get_align()~=m:get_align()) and not ptr:is_dm() then -- this line is pretty much needed or it crashes the server, just checks the the square isn't the 1 the monster is on, the monster is a different alignment from whoever is on that square, and that whoever on the square isn't a DM
					spell_fireball("vf",m,ptr,false,0,0,"200d2") -- not sure what the false,0 and 0 params are for, copied from highlord vae example
					
				end -- end the for loop if
			end -- end inner for loop
		end -- end outer for loop


	elseif (int_rand(19)==1) then -- on average every 19 seconds
		
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ifh"),m.x+1,m.y-1) -- casts flame wind in each direction
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ifh"),m.x+1,m.y) -- note that this doesn't cause any damage
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ifh"),m.x+1,m.y+1) -- damage comes later
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ifh"),m.x,m.y+1)
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ifh"),m.x-1,m.y+1)
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ifh"),m.x-1,m.y)
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ifh"),m.x-1,m.y-1)
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ifh"),m.x,m.y-1)	

		for xx=m.x-4, m.x+4 do
			for yy=m.y-4, m.y+4 do -- another double for loop to go over 4 squares in each direction from the dragon (the range of the wind spells)
				ptr=get_sent_ptr_xyz(xx,yy,m.map_level) -- gets reference to the square
				if((xx~= m.x or yy~=m.y) and ptr~=nil and ptr:get_align()~=m:get_align()) and not ptr:is_dm() then -- check target is valid
				hurt(ptr.id, int_rand(100)+100, "Fire Breath") -- cause 100-200 damage and say "Fire Breath" in local
				end -- end if checks
			end -- end inner for
		end -- end outer for
	

	elseif (int_rand(10)==1) then -- roughly every 10 seconds
		spell_fireball("vf",m,tgt,false,0,0,"30d5") -- casts fireball dealing 30-150 damage to single target
	end -- end if
end -- end heartbeat function


-- END YIN


function yang_init(m) -- pretty much the same, won't be as much comments here
	
	gTimer=0
	gYangDead=0
	m:unlearn_spells()
	m:learn_spell("ice") -- ice wind
	m:learn_spell("aep")
	m:learn_spell("vog")
	m:set_magic_resistance(4000)
	m:set_name("Yang")
	m:set_align(ALIGN_EVIL)
	m:set_hp_max(100000)
	m:set_intel(5000)
	m.mana = 300
	m:set_dmg_dice(100)
	m:set_dmg_sides(3)
	m:set_thaco(300)
	m:set_base_ac(20)
	
	m.immune_to_glassing=true
	m.death_func="yang_dies"
	m.heartbeat_func="yang_actions"

end


function yang_dies(m)

	local_msg(m,"Yang has melted")
	gYangDead=1

  if(gYinDead==1) then
	 -- m.xp_kill=500000
	x=math.random(1,10)

	if(x==1) then drop=0x1d3c035		-- + 29 str BR tower shield -- here theres 1 more digit in the item code than the weapons, this is because with a single digit values can only go as high as 15, with a 7 digit code we can get higher stat values
	elseif(x==2) then drop=0x1d2e090 -- + 29 int addy padded leggins
	elseif(x==3) then drop=0x1d20042 -- + 29 int chain coif
	elseif(x==4) then drop=0x1d4007a -- + 29 dex amulet -- another example, 1d = 29, 4 = dex, 0 = non-tinted, 07a = code for amulet
	elseif(x==5) then drop=0x1e40094 -- + 30 dex gi legs
	elseif(x==6) then drop=0x1e30088 -- + 30 str gi torso
	elseif(x==7) then drop=0x1f3d072 -- + 31 str glass ring
	elseif(x==8) then drop=0x1f2d073 -- + 31 int glass ring
	elseif(x==9) then drop=0x1946132 -- + 25 dex silver swampies
	elseif(x==10) then drop=0x204c087 -- + 32 BR field plate dex (again a rather stupid drop so it has to be trans'd)
	end
	local_msg(m,drop) -- another debug because items weren't dropping properly, still a little temperamental, not sure why
	drop=set_as_unidentified(drop)
	map:add_item(m.x,m.y,1,drop,true)
	drop=set_as_unidentified(drop)
	update_everyones_fov(m) -- make it visible
	local_msg(m, "Yin and Yang have been banished from this land!")
  end
end





function yang_actions(m)

if(gYinDead==1 and gTimer < 60) then
	gTimer = gTimer + 1
end

if(gYinDead==1 and gTimer>=60) then
local_msg(m,"Yin emerges from a burst of flames")
mc=spawn_near_id(0x22c,m.id) -- respawn fire drag
yin_init(mc)
end


m:set_health(HN_WOUNDED,0)
m:set_health(HN_HEXED,0)
m:set_health(HN_HELD,0)

	if int_rand(20)==1 and m.target_id>=0 then
		
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ice"),m.x+1,m.y-1)
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ice"),m.x+1,m.y)
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ice"),m.x+1,m.y+1)
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ice"),m.x,m.y+1) -- casts ice wind in all 8 directions
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ice"),m.x-1,m.y+1)
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ice"),m.x-1,m.y)
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ice"),m.x-1,m.y-1)
	    simple_send_event(m.id,EVENT_MAGIC,spells:get_spell_id("ice"),m.x,m.y-1)	

		for xx=m.x-4, m.x+4 do
			for yy=m.y-4, m.y+4 do
				ptr=get_sent_ptr_xyz(xx,yy,m.map_level)
				if((xx~= m.x or yy~=m.y) and ptr~=nil and ptr:get_align()~=m:get_align()) and not ptr:is_dm() then
				set_health(ptr.id,HN_HELD, 5)
				hurt(ptr.id, int_rand(100)+150, "You are frozen solid by Yang's Ice Breath")
				end
			end
		end


	elseif (int_rand(10)==1) then
	       spell_chain_lightning("vog",m,ptr,false,0,0,"30d6") -- casts vog that bounces between players (like the mage at the bottom of black mountain)
	end

end
--
-- END YANG
--END EVENT
A balanced diet is a cookie in each hand :jam:

mud
I once posted in TFIOOC!
Posts: 134
Joined: Wed Nov 09, 2005 12:29 pm

Re: Scripting questions

Post by mud » Sun Sep 05, 2010 11:35 pm

@hellslave
Thank you! Very helpful. Been looking over that and other examples a bit, I'll probably try my hands at some mob stuff soon.

@All
In the meantime, I wrote out a couple of other basic things and I have more questions if anyone has a minute.

First one, started out pretty simple. This is meant to be put as the script function of a 'stp' feature, and hopefully kill anyone who steps on it while visible. (I know this is already done in another map, and I don't plan on using exactly this, just a test)

Code: Select all

function kill_visible(x, y, z)
    sent = get_sent_ptr_xyz(x, y, z)
    if sent:is_visible() then
        hurt(sent.id, sent:get_hp_max(), "Only a Fleshwound")
    end
end
Questions:
  1. Is this the right function signature for being attached to a stp feature? I think I saw that somewhere, but can't seem to find it now.
  2. If so, what are the x and y my function gets called with? Of the feature, or the destx and desty from the feature properties?
  3. How does get_sent_ptr_xyz(...) work if there is more than one player on a square?

This is a little more complicated. I want to have a special location on the map (the altar). If anyone drops food there, it will be consumed, and a message sent out.

Code: Select all

local altar = {x = 2, y = 2}

local function spawn_controller(lvl)
    map = get_map_ptr(lvl)
    m = map:get_mon_ptr(0, 0)
    if not m then -- controller not there
        m = spawn_at(0x212, 0, 0) -- 0x212 = spider
        m.immoble = true
        m:set_align(ALIGN_GOOD)
        m:set_health(HN_HELD, -1)
        m:set_health(HN_HIDING, -1)
        m:set_heartbeat_function("hungry_altar_heartbeat")

function load_map_252(lvl)
    spawn_controller(lvl)
end

function hungry_altar_heartbeat(m)
    map = get_map_ptr(m.map_level)
    c = map:get_item_code(altar.x, altar.y)
    owner = map:get_item_owner(altar.x, altar.y)

    if wl:is_legit(c) and wl:is_food(c) then
        map:remove_item(altar.x, altar.y)
        update_everyones_fov(altar.x, altar.y, m.map_level)        
        sent = get_sent_ptr(get_player_id_from_name(owner))
        if sent then
            local_msg(sent, "Thanks for the meal, " .. owner)
        end
    end
end
Questions:
  1. Is all that jazz with the controller and the heartbeat the right thing to do, or is there a better way?
  2. Does map:get_item_owner(x,y) have meaning for dropped items, or is that only for loot from monsters/chests?
  3. If that function won't work, is there some other way I can tell who dropped something?
  4. What does the map:get_item_code(x,y) function do with piles? Do I only get the top item?
  5. Same question for map:remove_item, does that just remove the top item in a pile?
I guess I'll keep it to that for now, maybe see if those are totally wrong before I post anything else.

Any help would be greatly appreciated.

User avatar
hellslave
I used to bake rockcakes in my bakery.
Posts: 162
Joined: Sun Jun 20, 2004 9:40 pm

Re: Scripting questions

Post by hellslave » Mon Sep 06, 2010 1:18 am

In lua it seems you can't pass parameters into functions unless it's called from another function so I'm not sure where you'd be getting your x,y,z params from (could be wrong, haven't used a stp function yet). The way this was done in deja vous is: get_sent_ptr_xyz(x,y,lvl) where you've already set up the x, y and level values from within the function. If you want to do it across a range of tiles you'll want to use a double for loop like in my script for the radial attacks.

You'll also want to throw in an extra couple of checks when you check if they're visible. Haven't tested out the is_visible() function however deja vous does it using the get_health function with enums for invisible or hiding. About those extra checks, what if sent is null? what if the player is already dead? and presumably you also only want it to affect players rather than monsters too? For this you'll want:

Code: Select all

if send~=nil and sent.id < 100 and sent.hp > 0 then
~= is lua's way of doing not equal, id's below 100 are reserved for players, above that is monsters/npcs.

I'd also change the value for how much you're hurting them for, as if they walk across the step with 4 hp it seems a little odd to me to be hitting them for 800 say. might be easier just directly accessing the hp of the player with sent.hp


For the hungry altar, the spawn controller is how it's done in nizweideux, No need to worry about setting health params, just put it somewhere inaccessible in the map (also i'm not sure if setting the spawner to HN_HELD will prevent it from running its heartbeat function, I'd imagine it will). You're getting a pointer to the map, this is never used anywhere so you can get rid of that line. Not sure about the get_mon_ptr, wouldn't it be easier checking the location doesn't have anything there (get_sent_ptr_xyz(x,y,lvl) would be nil) and then spawning it if the location is free? This method seems to be the easiest way to allow timers across the whole map, missing an "end" to your spawn controller function too. On to the actual altar code. what is wl that you're calling the functions is_legit and is_food from? Lastly the message displayed attached owner to the end, I think owner will be the id number of the player rather than their name, it'd be owner.name.


Questions:
A - it seems to be the easiest way to do it
B - When an item is dropped the owner becomes nil
C - Not sure how you can do this
D - It'll most likely only get the top item, yes
E - That will only remove the top item, to destroy a pile use map:destroy_pile(x,y)
A balanced diet is a cookie in each hand :jam:

mud
I once posted in TFIOOC!
Posts: 134
Joined: Wed Nov 09, 2005 12:29 pm

Re: Scripting questions

Post by mud » Mon Sep 06, 2010 7:33 am

I kind of chopped up your post to just respond to the parts I felt needed response, hope you don't mind. The parts I took out I didn't ignore or anything, just not quoted. :)

Thanks very much for the response.
hellslave wrote:In lua it seems you can't pass parameters into functions unless it's called from another function so I'm not sure where you'd be getting your x,y,z params from (could be wrong, haven't used a stp function yet).
Ah, yeah, I don't really know what the function is called with. I assume that the call comes from code I can't see, so I really just guessed from what I thought I remembered seeing...I guess I'll have to wait for someone who knows, or I'll look back over the docs I have in the meantime.
hellslave wrote: You'll also want to throw in an extra couple of checks [...]
Hmm, yeah, good advice. Will be difficult to assume anything of the functions I'm calling, so I'll have to do that a lot.
hellslave wrote: For the hungry altar, the spawn controller is how it's done in nizweideux, No need to worry about setting health params, just put it somewhere inaccessible in the map (also i'm not sure if setting the spawner to HN_HELD will prevent it from running its heartbeat function, I'd imagine it will).
I thought it would be fine from reading some of the boss scripts I've seen, but you're right, there's little reason to do that, I'll take it out. I already have planned small areas on each map where I can put controller(s) without them getting into trouble and such.
hellslave wrote: On to the actual altar code. what is wl that you're calling the functions is_legit and is_food from?
That's from the eao.pkg.cpp file, apparently it's the item info database. Line 43, and then lines 337 and up (in eao.pkg.cpp). If I used it correctly is another question, but I think I did.
hellslave wrote: Lastly the message displayed attached owner to the end, I think owner will be the id number of the player rather than their name, it'd be owner.name.
I think it is a string actually, at least that's what eao.pkg.cpp says. I assumed that that was the player name, but could always be something else. Anyway, if that's not set for dropped items, I'll have to use some other system anyway. I have a few ideas that should work.

So to recap, I think the only unanswered questions for anyone out there are:
- How does get_sent_ptr_xyz(...) handle multiple sentients in the same position? I know players can be on each other, and monsters can be on (hidden) players. I'm assuming I only get one of the stack? If so, is there a way to get them all (or to get all players in an area?).
- What function signature should my handler for stp features have? In maped you only specify the function name as far as I see, so I can't exactly tell. Are those listed anywhere, or, are they mostly the same maybe? I'm pretty sure in lua you can just ignore passed in args if you feel like it, but some of them could be really useful it seems.
Looks like the signature is func(id, x, y, z). Found it at viewtopic.php?p=41531#p41531
Last edited by mud on Wed Sep 08, 2010 4:59 pm, edited 3 times in total.

User avatar
hellslave
I used to bake rockcakes in my bakery.
Posts: 162
Joined: Sun Jun 20, 2004 9:40 pm

Re: Scripting questions

Post by hellslave » Mon Sep 06, 2010 7:45 am

mud wrote:That's from the eao.pkg.cpp file, apparently it's the item info database. Line 43, and then lines 337 and up (in eao.pkg.cpp). If I used it correctly is another question, but I think I did.
Not sure if this is available in the lua or whether it's going to treat it as a new variable within the function scope (hopefully egg can clarify this)
Had a rake around in the scripts and yeah, it does have access to wl so that should be fine
mud wrote: I think it is a string actually, at least that's what eao.pkg.cpp says. I assumed that that was the player name, but could always be something else.
just from looking at the blood queen code when it specifies who the blood queen has slashed it uses tgt.name although thats taking it from get_sent_ptr so yeh it could well be the name, that would actually make a lot more sense
A balanced diet is a cookie in each hand :jam:

mud
I once posted in TFIOOC!
Posts: 134
Joined: Wed Nov 09, 2005 12:29 pm

Re: Scripting questions

Post by mud » Mon Sep 06, 2010 5:33 pm

Followup on one of my old questions: I asked egg in game about get_sent_ptr_xyz(), it just gets the visible one.

mud
I once posted in TFIOOC!
Posts: 134
Joined: Wed Nov 09, 2005 12:29 pm

Re: Scripting questions

Post by mud » Tue Sep 07, 2010 10:27 pm

I made a maze generation function, it's attached. Any comments welcome.

Planning on having some fun with it in a map I'm working on. Actual walls might be too obnoxious due to the lack of visibility, maybe just different color floor tiles and some traps or something,
You do not have the required permissions to view the files attached to this post.

mud
I once posted in TFIOOC!
Posts: 134
Joined: Wed Nov 09, 2005 12:29 pm

Re: Scripting questions

Post by mud » Mon Sep 13, 2010 6:31 pm

Looking at euo.pkg.cpp:

Code: Select all

int get_free_rand_xy(int *x, int *y, bool want_water, bool not_on_ore_spawner);
How does this get translated into a Lua function? Afaik, Lua doesn't have pointers to return the result in, so are there multiple return values? What is the int that is returned? Success/failure code? Does that go before the x and y in the return, or maybe nil is returned on failure, x and y on success?

Also, a separate thought: I'm thinking about doing a lot of tile changes at one time (like, on the close order of 100 updates at once). Is that going to cause any problems if people are on the map and it's done continuously? What about if only done once in a while? Is there some way I can save bandwidth, for example by doing a bunch of calls to CMap:set_tile(...), and then causing them all to be sent as one bunch? Would one of the update_*_fov(...) functions do that, or is fov only like items and mobs? Or is it even necessary to do that? Should I just call set_and_send_new_tile(...) and it'll intelligently queue all the changes up in one big packet or something?

Sorry, that's kind of a dense block of questions...

Post Reply