//! zinclibraryMarkOfArcherrequiresSpellEvent, Table
{
constantintegerSPELL_ABILITYID = 'A000'; //The spell ability.constantintegerBONUS_ABILITYID = 'A001'; //The passive ability that is added to the caster.constantbooleanADD_ATTACKS = true; //If a spell is still active when its caster casts it again on//the same target, should the attack limit of the two be added//together or should the old remaining attacks be discarded?functionAttackCount( integerlevel ) -> integer
{ return5+level*5; } //The number of attacks that the spell will remain active for.//----- END OF SPELL CALIBRATION -----//structmark
{
unittarget, caster; integerlevel; //Spell data.staticHandleTabletargetTable, casterTable; //Tables for quick instance access.thistypenext, prev; //The next and previous instances in the target's list of spells.integerattacks; //How many attacks left until the spell stops.methoddestroy()
{
if (next==0 && prev==0) {
targetTable.flush(target); //This is the last item in the list, flush the target table.
} else {
if (next!=0) next.prev=prev; //There is an item after this one in the list, relink it.if (prev!=0) prev.next=next; //There is an item before this one in the list, relink it.elsetargetTable[target]=integer(next); //This was the first item in list, move forward.
}
UnitRemoveAbility(caster, BONUS_ABILITYID); //Remove the bonus ability from the caster.casterTable.flush(caster); //Flush the caster table.target=null; caster=null; //Cleanup the handle variables.// do not reset next and prev, they may still be needed in the calling function.deallocate();
}
staticmethodcreate( unitt, unitc, integerlvl ) -> thistype
{
thistypethis;
thistypethat = thistype(targetTable[t]); //See if the caster already has this spell cast on an enemy.if (that!=0) {
if (that.target==t) { //If the existing instance has the same target then simply update and return it.staticif (ADD_ATTACKS) that.attacks=that.attacks+AttackCount(lvl);
elsethat.attacks=AttackCount(lvl);
returnthat;
} else { //If the existing instance has a different target then destroy it and allocate a new one.that.destroy();
this=allocate();
}
}
UnitAddAbility(c, BONUS_ABILITYID); //Add the bonus ability to the caster.SetUnitAbilityLevel(c, BONUS_ABILITYID, lvl); //Set the level of the bonus ability accordingly.UnitMakeAbilityPermanent(c, true, BONUS_ABILITYID); //Prevent morph abilities from removing this ability.target=t; caster=c; level=lvl; //Store spell data values.attacks=AttackCount(lvl);
//Insert the spell instance at the start of the target's linked list:that = thistype(targetTable[t]); //See if the target is already under the effect of this spell.if (that==0) {
next=0; prev=0;
} else {
that.prev=this;
next=that; prev=0;
}
//Store the spell instance in the tables.targetTable[t]=integer(this); casterTable[c]=integer(this);
returnthis;
}
staticmethodonDeath()
{
thistypethis = thistype(targetTable[GetTriggerUnit()]);
while (this>0) //Destroy all instances in the unit's list.
{
this.destroy(); //When this is called on the last instance it will flush the table.this=this.next; //Destroy method does not reset the next value so this works.
}
}
staticmethodonAttack()
{
thistypethis = thistype(casterTable[GetAttacker()]);
if (this>0) {
if (target!=GetTriggerUnit()) destroy(); //If the caster has switched targets, destroy.else {
attacks=attacks-1;
if (attacks<=0) destroy(); //If the spell ran out of attacks, destroy.
}
}
}
staticmethodonSpellEffect()
{
integerlvl = GetUnitAbilityLevel( SpellEvent.CastingUnit, SPELL_ABILITYID );
thistype.create( SpellEvent.CastingUnit, SpellEvent.TargetUnit, lvl );
}
staticmethodonInit()
{
triggert;
targetTable=HandleTable.create();
casterTable=HandleTable.create();
RegisterSpellEffectResponse( SPELL_ABILITYID, thistype.onSpellEffect );
t=CreateTrigger();
TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH);
TriggerAddAction(t, functionthistype.onDeath);
t=CreateTrigger();
TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED);
TriggerAddAction(t, functionthistype.onAttack);
}
}
}
//! endzinc

P.S.: This would have been better with ABuff, but you already know that. :P

Goddamit Anitarf, you did not announce your work, your solutions is in ZINC, and there is no demo map.

There was no mention of demo maps or Zinc in the first post, so you have no business complaining about those. As for not announcing my work, it wasn't very likely that someone else would strt coding right away like I did and even if someone else did do that then all I'd be wasting would have been my time which, again, does not concern you. I guess I'll announce any further intentions from now on so people won't think that I might be working on a spell that I actually have no intention of making.

Quote:

Did you even try to compile this?

Yes, it compiles.

Quote:

Oh I am sure it is ok, but you just keep half-assing your work.

I do not agree with that characterization. Sure, I avoid opening the object editor unless it is absolutely necessary, but as far as code is concerned I do not cut corners. I included everything from a proper calibration section to detailed comments in the code.

Quote:

For the future reference, please no ZINC.
I am trying to be consistent with my map code.

I don't know why you're asking for contributions, then. Even vJass code from other users won't be the same as yours. Furthermore, I don't see what purpose this consistency serves. If you rewrite this in vJass it won't function any differently, it will be just a waste of your time.

Quote:

PS: I finally got it, I can make you do all my buff spells,
you will do it just so you can bitch about me not using ABuff

Don't count on it, especially if you make demo maps and vJass explicit requirements. Doing that will greatly reduce the odds of me writing any further contributions.

I avoid opening the object editor unless it is absolutely necessary
...
especially if you make demo maps and vJass explicit requirements.

Do you honestly believe I opened this thread because I lack in coding skills?

What good are contributions if they don't save me time.
You coded this spell in about 5 minutes and that is exactly how much your contribution is worth. If you bothered to open object editor and spend 5 more minutes on it by finding appropriate abilities and icons it would double the value of your contribution.
If you even bothered to write the tooltips it would triple the value of your contribution.

So as you see pure coding may look like the most important part but in terms of value it is below half and so I call it half-assed work.

Of course me requiring the work to be done properly will greatly reduce the probability of it being done as you said.
It is because the full work has bigger time price, but than again that is what actually makes it valuable.