| 12-09-2006, 03:58 PM | #1 |
I've written something that I think would perhaps fit into the Caster System. When casting a spell, for instance on an area, you always have to add lots of checks for everything so that the spell doesn't target the wrong unit. This is an "über-script" :p which allows units to be checked with just one function call. Currently it has the capability to check if the unit is: Dead or Alive Allied or Enemy Invulnerable or vulnerable Structure or non-structure Flying or non-flying Also, it always generate FALSE if the target unit is a casting unit. In the bottom there are short-forms of the script, so that one won't have to enter the entire function for simple spells. Code:
//! library IsUnitSpellTarget needs CasterSystem //*********************************************************************** //* * //* IsUnitSpellTarget 0.5 * //* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ By Themerion * //* Requires: * //* ¯¯¯¯¯¯¯¯¯ * //* * //* - The CasterSystem * //* * //*********************************************************************** function I2B takes integer i returns boolean if(i==0) then return false endif return true endfunction globals integer CHECK_NOCHECK = -1 integer CHECK_FALSE = 0 integer CHECK_TRUE = 1 integer CHECK_INV_ALLIES=-1 integer CHECK_INV_ENEMIES=0 endglobals //================================================================================================ function IsUnitSpellTarget takes unit target,player caster,integer ally,integer alive,integer inv,integer struct,integer fly returns boolean if(GetUnitTypeId(target)==cs_CasterUnitId) then return false endif // Check if the target is an ally or an enemy. if(ally!=CHECK_NOCHECK) then if(I2B(ally)!=IsUnitAlly(target,caster)) then return false endif endif // Check if the target is alive or dead. if(alive!=CHECK_NOCHECK) then if(I2B(alive)!=(GetUnitState(target,UNIT_STATE_LIFE)>0.5)) then return false endif endif // Check if the target is invulnerable or vulnerable. if(inv!=CHECK_NOCHECK) then if(I2B(inv)!=IsUnitInvulnerable(target)) then return false endif endif // Check if the target is a structure or not. if(struct!=CHECK_NOCHECK) then if(I2B(struct)!=IsUnitType(target,UNIT_TYPE_STRUCTURE)) then return false endif endif // Check if the target is a flying unit. if(fly!=CHECK_NOCHECK) then if(I2B(fly)!=IsUnitType(target,UNIT_TYPE_FLYING)) then return false endif endif return true endfunction //================================================================================================ function IsUnitGroundSpellTarget takes unit u returns boolean return IsUnitSpellTarget(u,null,CHECK_NOCHECK,CHECK_TRUE,CHECK_NOCHECK,CHECK_FALSE,CHECK_FALSE) endfunction function IsUnitFlyingSpellTarget takes unit u returns boolean return IsUnitSpellTarget(u,null,CHECK_NOCHECK,CHECK_TRUE,CHECK_NOCHECK,CHECK_FALSE,CHECK_TRUE) endfunction function IsUnitDeadSpellTarget takes unit u returns boolean return IsUnitSpellTarget(u,null,CHECK_NOCHECK,CHECK_FALSE,CHECK_NOCHECK,CHECK_FALSE,CHECK_FALSE) endfunction // * * * * * * * * * * * function IsUnitEnemySpellTarget takes unit u, player p returns boolean return IsUnitSpellTarget(u,p,CHECK_FALSE,CHECK_TRUE,CHECK_INV_ENEMIES,CHECK_FALSE,CHECK_NOCHECK) endfunction function IsUnitEnemyGroundSpellTarget takes unit u, player p returns boolean return IsUnitSpellTarget(u,p,CHECK_FALSE,CHECK_TRUE,CHECK_INV_ENEMIES,CHECK_FALSE,CHECK_FALSE) endfunction function IsUnitEnemyFlyingSpellTarget takes unit u, player p returns boolean return IsUnitSpellTarget(u,p,CHECK_FALSE,CHECK_TRUE,CHECK_INV_ENEMIES,CHECK_FALSE,CHECK_TRUE) endfunction function IsUnitEnemyDeadSpellTarget takes unit u, player p returns boolean return IsUnitSpellTarget(u,p,CHECK_FALSE,CHECK_FALSE,CHECK_NOCHECK,CHECK_FALSE,CHECK_FALSE) endfunction // * * * * * * * * * * * function IsUnitAlliedSpellTarget takes unit u, player p returns boolean return IsUnitSpellTarget(u,p,CHECK_TRUE,CHECK_TRUE,CHECK_INV_ALLIES,CHECK_FALSE,CHECK_NOCHECK) endfunction function IsUnitAlliedGroundSpellTarget takes unit u, player p returns boolean return IsUnitSpellTarget(u,p,CHECK_TRUE,CHECK_TRUE,CHECK_INV_ALLIES,CHECK_FALSE,CHECK_FALSE) endfunction function IsUnitAlliedFlyingSpellTarget takes unit u, player p returns boolean return IsUnitSpellTarget(u,p,CHECK_TRUE,CHECK_TRUE,CHECK_INV_ALLIES,CHECK_FALSE,CHECK_TRUE) endfunction function IsUnitAlliedDeadSpellTarget takes unit u, player p returns boolean return IsUnitSpellTarget(u,p,CHECK_TRUE,CHECK_FALSE,CHECK_NOCHECK,CHECK_FALSE,CHECK_FALSE) endfunction // * * * * * * * * * * * //! endlibrary //"Forced by WE" //(quote from Vexorian) // function InitTrig_IsUnitSpellTarget takes nothing returns nothing endfunction |
| 12-09-2006, 06:08 PM | #2 |
Although not quite equivalent in efficiency, wouldn't DamageOptions + CasterCastAbilityGroup do the same? |
| 12-09-2006, 09:13 PM | #3 |
Yes. "Although not quite equivalent in efficiency", wouldn't CasterCastAbility work the same with CreateUnit + IssueOrderTargetingUnit? ( Yes, I know this is by far a larger function than CasterCastAbility. ) My idéa with IsUnitSpellTarget is to avoid the following in every spell/ability-script: (and in large maps, there can be 50 or more of these) Code:
if(IsUnitInvulnerable()==false) then
if(IsUnitCaster()==false) then
if(IsUnitStructure()==false) then
if(IsUnitFlying()==false) then
if(IsUnitAlive()==true) then
if(DoesUnitEatApples()) then
if(WeWantToDoSomething()) then
// weshould start the statements soon :P
endif
endif
endif
endif
endif
endif
endif
// this is an exaggeration =)I simply thought that I would make things easier for myself. Although, I can understand if you think that IsUnitSpellTarget is a bit much code for just some convenience. D'you think that I can post it as a resource so that if somebody wants it, then they can download it? |
| 12-11-2006, 01:59 PM | #4 |
or you could use boolexprs... I like them a lot. All you have to do is use a blizzard var like bj_GroupEnumOwningPlayer to store the owning player of the casting unit when checking if something is an enemy. JASS:function SpellConditions takes nothing returns boolean local boolean a = whatever local boolean b = whatever local boolean c = IsUnitEnemy(GetFilterUnit(), bj_GroupEnumOwningPlayer) return a and b and c endfunction function Spell takes nothing returns nothing ... local boolexpr b = Condition( function SpellConditions ) set bj_GroupEnumOwningPlayer = GetOwningPlayer(GetTriggerUnit()) ... call GroupEnumUnitsInRange(g, x, y, b) //do stuff to all the units in the group ... call DestroyBoolExpr(b) set b = null endfunction for this purpose I also made a UnitEvalBoolExpr function which checks if a single unit matches boolexpr conditions. |
| 12-12-2006, 08:16 PM | #5 |
That really look useful! I've never used boolean expressions before (I read somewhere that they were ineffective and leaking. I suppose that the leaking thing is only if they are not destroyed though :P) Thanks a lot! I still think thou' that every map need some kind of standardized SpellConditions... (instead of rewriting them for each spell) |
| 12-12-2006, 09:47 PM | #6 |
This way makes it really easy to copy and paste the spell conditions into a configuration area above each spell, and make whatever modifications you want. |
