DSB's idle

This forum is for the Lua scriptable clone of DM/CSB called Dungeon Strikes Back by Sophia. Use DSB to build your own highly customised games.

Moderator: Sophia

Forum rules
Please read the Forum rules and policies before posting.
Post Reply
Remy
Craftsman
Posts: 111
Joined: Wed Sep 05, 2007 5:24 pm
Contact:

DSB's idle

Post by Remy »

I was working on a EOB-esque two-weapon system for DSB, and was wondering about a few things concerning how DSB's champion idle works.
First, I noticed that it blocks mouse clicks in the attack option area for that champion if it's above 0. Under the old system, this was probably neccessary, but now the renderer handles the blocking by simply not creating a 'msgzone'. I'm wondering if this is redundant, or is there another reason for it.
Also, does the idle do anything else besides that (and act as a timer to tell the renderer it can draw the msgzone again)? I ask because in the system I used, I pretty much bypass the idle entirely (well, I still use it so that I didn't have to rewrite all the 'methods.lua' code, but I immediately set it to 0 after I get the value), and it seems to work, but I'm wondering if I'm unknowingly introducing side-effects I don't know about.
User avatar
Joramun
Mon Master
Posts: 925
Joined: Thu May 25, 2006 7:05 pm
Location: The Universe

Post by Joramun »

Hey ! :shock: Where is your R ???

If every one on the forum drops the last letter, things will get very confusing...

About the methods :
I've got a problem with my two-handed weapon : If the player opens the method menu, and then remove the left hand dummy item, he still gets a free two-handed attack.
I don't know how to solve that, in fact, I accepted it in the first place (as the same things happens with spellcasting) except by quickly removing and replacing the weapon in the right hand...
What Is Your Quest ?
Remy
Craftsman
Posts: 111
Joined: Wed Sep 05, 2007 5:24 pm
Contact:

Post by Remy »

If every one on the forum drops the last letter, things will get very confusing...
:lol: The 'R' was there out of habit - alot of places already have "Remy"s registered, but I prefer Remy to RemyR (it's also easier to type).

I'm not sure I quite understand you're problem (actually, I understand the problem, I don't understand what you're doing), so if I have this wrong, my apologies.
You have an weapon that requires two hands to use, so you "block" the left hand when the item is equipped by placing a dummy item into it. Or is it that to use the item, the player must combine two items (one in each hand)?
If it's the first, what happens normally when the player removes the dummy item? The way I would do this is with 'fit' and 'from' event functions on the main item. When it's placed in the right hand, spawn a new "dummy" item in the left (if there's room - if there's not, 'fit' should return false). When the dummy item is removed, you swap it for the main item (push the main item from the right hand to the mouse pointer) and destroy the dummy item.
I'm not sure how to handle the second scenario, though (two combined items), short of doing what you said - using the 'from' event to pop the right hand item out momentarily to clear the method menu. But, really, are they getting anything for free? If they use the method, they'll still get hit with the stamina drain and the delay penalty, right? So all they get to do is move the dummy item around, which really doesn't do them any good. Granted, it'd look wierd, but it's not rule-breaking per-se.
User avatar
Joramun
Mon Master
Posts: 925
Joined: Thu May 25, 2006 7:05 pm
Location: The Universe

Post by Joramun »

Basically, the two handed axe works this way :
When equiped, it offers only one method : "Wield".
If the left-hand is free, the method wield fills it with a dummy item, and sets an exvar for the two handed axe.
If the exvar is set, the two handed axe gives 3 attack methods, instead of the wield method.
If the dummy item is manipulated, it is destroyed and the exvar is cleared.
If the axe is manipulated, the dummy item is destroyed and the exvar is cleared.
What Is Your Quest ?
Remy
Craftsman
Posts: 111
Joined: Wed Sep 05, 2007 5:24 pm
Contact:

Post by Remy »

Well, just my opinion, but you might consider using dsb_push_mouse() to push the "true" axe to the mouse when a player tries to remove it from the left hand after you clear the exvar and destroy the dummy. It'll clear the method menu for you, and it fits logically with the player's actions (they're trying to unequip the axe - why should they get nothing?).
User avatar
Joramun
Mon Master
Posts: 925
Joined: Thu May 25, 2006 7:05 pm
Location: The Universe

Post by Joramun »

Well, for now the dummy item is just a hand with a doted outline to show it's being used.
I can consider replacing that by a shaded version of the axe, but I don't want to double all my icons just for that,
so I would have to create a shade mask... It can get really complicated.

I set "after_l_hand" for the dummy item and "after_r_hand" for the axe to the following function :

Code: Select all

function un_wield(self,id,who)
	local l_hand = dsb_fetch(CHARACTER, who, INV_L_HAND, 0)
	local r_hand = nil
	local mouse = dsb_fetch(MOUSE_HAND, 0, 0, 0)
	
	if (l_hand and (dsb_find_arch(l_hand).class == "SECOND_HAND" ) ) then
		if exvar[mouse] then
			exvar[mouse].two_hands = nil
		end
		exvar[l_hand]=nil
		dsb_delete(l_hand)
	elseif (mouse and  (dsb_find_arch(mouse).class == "SECOND_HAND") ) then
		r_hand = dsb_fetch(CHARACTER, who, INV_R_HAND, 0)
		if exvar[r_hand] then
			exvar[r_hand].two_hands = nil
		end
		exvar[mouse]=nil
		dsb_pop_mouse()
		dsb_delete(mouse)
	end
end
And the attack method function for the axe :

Code: Select all

function method_wield(name, ppos, who, what)
	local item_id = nil
	local weapon = nil
	local hand = dsb_fetch(CHARACTER, who, INV_L_HAND, 0)
	
	if (what) then weapon = dsb_find_arch(what) end
	
	if (hand) then
		dsb_write(system_color, dsb_get_charname(who) ..
				" NEEDS HIS LEFT HAND TO WIELD THE WEAPON")
		dsb_set_idle(ppos, dsb_get_idle(ppos) + 1)		
	else
		item_id = dsb_spawn("second_hand", CHARACTER, who, INV_L_HAND, 0)
		
		if (not exvar[what]) then
			exvar[what] = { two_hands = true }
		else
			exvar[what].two_hands = true
		end
		
		dsb_write(system_color, dsb_get_charname(who) ..
				" WIELDS HIS WEAPON WITH BOTH HANDS")
		dsb_set_idle(ppos, dsb_get_idle(ppos) + 2)
	end
end
What Is Your Quest ?
User avatar
Sophia
Concise and Honest
Posts: 4240
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Post by Sophia »

Remy wrote:First, I noticed that it blocks mouse clicks in the attack option area for that champion if it's above 0. Under the old system, this was probably neccessary, but now the renderer handles the blocking by simply not creating a 'msgzone'. I'm wondering if this is redundant, or is there another reason for it.
It's redundant now. I forgot to take it out. :)
Remy wrote:Also, does the idle do anything else besides that (and act as a timer to tell the renderer it can draw the msgzone again)?
No, all it does is tell the renderer what to do now, and save the designer some exvar hijinks (provided you want a close approximation of the DM system, anyway...)
Joramun wrote:I've got a problem with my two-handed weapon
You could always set an exvar on the dummy item that associates it with the real one, something like:

Code: Select all

exvar[item_id] = { controller = what }
Then you could add something like this to un_wield:

Code: Select all

if (exvar[id].controller) then
	dsb_push_mouse(exvar[id].controller)
end
That way, when you try to remove the dummy item, the axe will pop into hand instead-- and the attack method menu will disappear. (You will probably have to expand on this a little, to swap the item that's already in the mouse hand into the left hand, if the mouse hand is full, but you get the idea, I imagine)
Remy
Craftsman
Posts: 111
Joined: Wed Sep 05, 2007 5:24 pm
Contact:

Post by Remy »

I just noticed something; there isn't a way for an arch's 'onthrow' event to tell whether it was called from a mouse throw or a method throw.
Now, normally this doesn't matter, but it could lead to a potential problem if the designer is using both 'onthrow' events and making changes to calc_tpower and/or calc_throw to allow for different inventory locations to return different results (for example: a throw from the left hand is weaker than a throw from the right hand).
The problem comes from this: normally, you'd use dsb_lastmethod to determine which inventory slot the attack originated. But the game engine calls the 'onthrow' event directly (without a method call) if the arch is thrown with the mouse. dsb_lastmethod won't neccesarily match in this case (and if the mouse throw is the first "method" that champion used in the game, dsb_lastmethod will return 'nil', which could be bad). sys_mouse_throw handles this by using a global ('mouse_throwing_hand'), but if there's an 'onthrow' event, sys_mouse_throw is bypassed entirely.
This is, of course, a very limited problem (it's the only sort of special case - all other attacks that may call upon calc_tpower and calc_throw come from methods), and I only noticed it because my idle system doesn't have a universal way of handling 'onthrow' events. The only potential solution I see at the moment is to just use sys_mouse_throw to call the 'onthrow' event (the same way method_throw_obj does now) instead of the engine doing it directly, that way they can be overriden to also pass along a inventory location to the event -- but then, I might be inclined to think that because it also fixes my idle system problem.
User avatar
Sophia
Concise and Honest
Posts: 4240
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Post by Sophia »

If I'm understanding correctly, the main limitation is that on_throw doesn't know where the throw originated.

How about this?

I'll change the beginning of method_throw_obj to the following:

Code: Select all

    local used_method, att_loc = dsb_lastmethod(ppos)

	-- call the on_throw so we're consistent with sys_mouse_throw
	if (throw_arch.on_throw and throw_arch:on_throw(what, att_loc)) then
	    return true
	end
Now, an on_throw invoked from an attack method will provide the location.

The on_throw called by the engine before a mouse throw won't provide this parameter, because it's not really "originating" from anywhere. (If you want to use the same hack the DSB code does, go ahead and use the mouse_throwing_hand global) This way, you'll be able to know where the throw came from, or that the throw was from the mouse hand, because that'll show up as nil. Old code will still work because it's not expecting that paremter anyway.
Remy
Craftsman
Posts: 111
Joined: Wed Sep 05, 2007 5:24 pm
Contact:

Post by Remy »

That'll work. :)

I did some testing, and realized that I was half-wrong. I thought that if an on_throw existed for an arch, it would supercede sys_mouse_throw: in other words, the event function would have to handle all the power settings and stuff and pass all that to dsb_shoot all by itself, and sys_mouse_throw would never be called. I, of course, was wrong. (Which I would have realized if I'd given the method_throw_obj a second thought - 'cause if throw events handled the actual "Throwing", that method would throw things twice...)

The lesson today is test before you speak. :)

But still, if someone was using on_throw events, it might be helpful for the function to know if it was originating from a method (and which location) or from a general mouse throw.
User avatar
Sophia
Concise and Honest
Posts: 4240
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Post by Sophia »

Actually, you're half right both ways. :)

A non-nil (or non-false) return value from on_throw means "I've taken care of everything, don't do anything else." The normal attack method function (or sys_mouse_throw) won't be called. Otherwise, it will still proceed.

So, if you have a magic apple that turns into a ful bomb when you throw it, return false. If it just flat-out explodes when you try to throw it, return true. :)
Post Reply