HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

CS - suggested functions

12-09-2006, 03:58 PM#1
Themerion
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
Vexorian
Although not quite equivalent in efficiency, wouldn't DamageOptions + CasterCastAbilityGroup do the same?
12-09-2006, 09:13 PM#3
Themerion
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
grim001
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.


Collapse 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
Themerion
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
grim001
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.