Tutorial - DoAttack Event

DCurrent

Site Owner, OpenBOR Project Leader
Staff member
Everything you need to get started with the ondoattackscript event. The example script can be found here.


Cheers,
DC

 
Nice video. Have watched it all the way through. I think this will help lots of people and future modders ;)
 
ahhhhhhh. So its "ondoattackscript" and not just "ondoattack"?
I thought it was weird to name it just "ondoattack".

I remember I put this on the manual as is because is the way everybody calls it.

Using my current build, 6315, when I call it as "ondoattack", nothing happens. But once I change to "ondoattackscript", the engine closes and give me a "can't compile script".
Script compile error in 'ondoattackscript': Type line 9, column 4

But my code is the same of yours:
Code:
Type	= getlocalvar("attacktype");// Get attack type
 
The script doesn't do anything useful, just makes whoever has it immune to getting hit. It's just a boilerplate that I walk through in the video- the idea is that you would take that and add some logic of your own - like with O Ilusionista is doing.

My parry system is another example. I'll make a video on it when I can, but here's the quick rundown:

[list type=decimal]
[*]Every time the player presses block key, a global variable is populated with the elapsed time.
[*]When an entity's doattackscript runs, it works almost exactly like I outline, but the line that sets lasthitc to 0 is enclosed in another logic block. Immediately before that logic, my parry function is run.
[*]The parry function looks at current elapsed time and compares it to the last block press time recorded in step 1. If the the last press is within .25 second and a couple of other conditions pass (not busy doing something else, etc.), then the receiving entity's parry animation is played, the attacking entity gets a bit of delay time added to their current animation (this is in addition to whatever delay they already had), a visual block/parry flash is spawned, and the receiving entity gets a small MP boost. The function then returns a TRUE value. A little side note - mashing block won't work. There was no need to code in an anti mash check because in this module double tapping block triggers a backward dash. Side, SIDE note: I cheated while making the video by cranking the timing up to a full second. :P
[*]The extra logic block around lasthitc is just to verify if parry function returned true or false. If true, lasthitc is set to 0, and the attack is effectively nullified.
[/list]

You will find this to be far simpler and more effective than using the takedamagescript or any other post action method. There's no need to go back and "undo" anything. The hit never happens at all, nor do any resulting scripts, flashes, and so on.

Also remember this runs on the attacker entity too. You could it set up a lot of pre-damage vectors. It's also useful for making "zones", where you essentially use the collision system to mark out portions of an area for custom behavior.

The order looks like this:

[list type=decimal]
[*]Hit detected
[*]Defender's DoAttack
[*]Attacker's DoAttack
[*]Lasthitc verify
[*]Default hit behavior
[/list]

HTH,
DC
 
Just noticed I had linked to the wrong file. Derp! Fixed in OP.  ::)

DC
 
Thanks for the help, its working fine now :)

Here is what I am using :
Code:
void main()
{
	void self;      // Entity running event
	void other;     // Entity attacking or receiving vs. self.
	int which;      // Attacker or defender event?
	int hit_by_id;  // Entity ID of entity attack hit.
	int attack_id;  // Entity ID of entity that performed attack.
	int type;

	type	= getlocalvar("attacktype");// Get attack type
	self	= getlocalvar("self");
	other	= getlocalvar("other");
	which	= getlocalvar("which");
	
	// Is this a defending event?
	if(which == 0)
	{
		// IDs are not the same? This is how we prevent repeat
		// hits from the same attack.
		hit_by_id   = getentityproperty(self, "hitbyid");
		attack_id   = getlocalvar("attackid");
	
		// Different attack ID?
		if(hit_by_id != attack_id)
		{
		    // Is this the attack type we want? If so,
		    // set lasthit 0 (engine ignores attack hit).
		    if(type == openborconstant("ATK_NORMAL17"))
		    {
			changeopenborvariant("lasthitc", 0);
		    }			
		}				
	}
   
    	// Set hit id on self to attack ID for the next cycle.
	changeentityproperty(self, "hitbyid", hit_by_id);
}

Notes:
- I am not using EXCHANGE_RECIPIANT because my build version doesn't have it.
- Thanks to the reason above, I am using "which == 0". But I don't recommend it because, as DC had explained to me, this number had change on newer builds (and magic numbers are a bad idea anyway).



 
Back
Top Bottom