- Joined
- Sep 19, 2005
- Messages
- 169
Hi. A long time ago someone I know made a system for my map. The system is supposed to give units who are above the units they are attacking an increase in the amount of damage they do. The system works fine but in my tests the map crashes when there are too many units fighting at once. Is there maybe another damage detection system that is more efficient? The script was written a while ago. I'm going to use the system in my map for the 1v1 mode because theres a lot less units and the engine can handle the system.
Also I want don't want ships to be able to use this system because ships always fight on even ground. Can this be filtered by unit movement type (float) or something?
Code:
Also I want don't want ships to be able to use this system because ships always fight on even ground. Can this be filtered by unit movement type (float) or something?
Code:
JASS:
library BoolexprUtils initializer init
globals
boolexpr BOOLEXPR_TRUE=null
boolexpr BOOLEXPR_FALSE=null
endglobals
private function rettrue takes nothing returns boolean
return true
endfunction
private function retfalse takes nothing returns boolean
return false
endfunction
private function init takes nothing returns nothing
set BOOLEXPR_TRUE=Condition(function rettrue)
set BOOLEXPR_FALSE=Condition(function retfalse)
endfunction
endlibrary
library LightLeaklessDamageDetect initializer Init
// Creating threads off of this that last longer than the timeout below will likely cause issues, like everything blowing up (handle stack corruption)
// It seems that threads created by timers, rather than executefunc / .evaluate / .execute are not affected. Any threads created from the timer thread are fine.
// This being safe with even the usage laid out above isn't guarenteed. Use at own risk.
// If you start getting random bugs, see if commenting out the timer line below (see comments) helps
// If it does, report it in the thread for this script at [url]www.wc3campaigns.net[/url]
globals
private constant real SWAP_TIMEOUT = 600. // keep high; 600 should be about the right balance.
endglobals
globals
private conditionfunc array func
private integer funcNext = 0
private trigger current = null
private trigger toDestroy = null
private group swapGroup
private rect mapRect
endglobals
// One of the only accessible functions. Use it to add a condition. Must return boolean type, and then have return false at the end.
// Note that it's technically a condition, so if you put a wait in there, it'll die. But waits are lame anyway.
function AddOnDamageFunc takes conditionfunc cf returns nothing
call TriggerAddCondition(current, cf)
set func[funcNext] = cf
set funcNext = funcNext + 1
endfunction
// These inline. For avoiding feedback loops. Feel free to make your own wrapper function for damage functions using this.
function DisableDamageDetect takes nothing returns nothing
call DisableTrigger(current)
endfunction
function EnableDamageDetect takes nothing returns nothing
call EnableTrigger(current)
endfunction
// no more accessible functions, folks.
//! textmacro CGLeaklessDamageDetectAddFilter takes UNIT
// add here any conditions to add the unit to the trigger, example below, commented out:
// if GetUnitTypeId($UNIT$) != 'h000' then // where 'h000' is a dummy unit
call TriggerRegisterUnitEvent(current, $UNIT$, EVENT_UNIT_DAMAGED)
// endif
//! endtextmacro
private function AddEx takes nothing returns boolean
//! runtextmacro CGLeaklessDamageDetectAddFilter("GetFilterUnit()")
return false
endfunction
private function Enters takes nothing returns boolean
//! runtextmacro CGLeaklessDamageDetectAddFilter("GetTriggerUnit()")
return false
endfunction
private function Swap takes nothing returns nothing
local integer i = 0
local boolean b = IsTriggerEnabled(current)
call DisableTrigger(current)
if toDestroy != null then
call DestroyTrigger(toDestroy)
endif
set toDestroy = current
set current = CreateTrigger()
if not(b) then
call DisableTrigger(current)
endif
call GroupEnumUnitsInRect(swapGroup, mapRect, Filter(function AddEx))
loop
exitwhen i >= funcNext
call TriggerAddCondition(current, func[i])
set i = i + 1
endloop
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
local region r = CreateRegion()
local integer i = 0
set mapRect = GetWorldBounds()
call RegionAddRect(r, mapRect)
call TriggerRegisterEnterRegion(t, r, null)
call TriggerAddCondition(t, Condition(function Enters))
set swapGroup = CreateGroup()
set current = CreateTrigger()
loop
exitwhen i >= funcNext
call TriggerAddCondition(current, func[i])
set i = i + 1
endloop
call GroupEnumUnitsInRect(swapGroup, GetWorldBounds(), Filter(function AddEx))
// Commenting out the next line will make the system leak indexes and events, but should make it safer.
call TimerStart(CreateTimer(), SWAP_TIMEOUT, true, function Swap)
endfunction
endlibrary
JASS:
library AttackHeightAdvantage initializer Init requires LightLeaklessDamageDetect, BoolexprUtils
//Written by Pyrogasm for Psycomarauder
//
//It's pretty simple: just modify the below calculation however you like. Use teh maths!
//Only return the bonus damage you'd like to apply (or subtract, if you give it negative damage)
globals
private constant integer ORB_ABILITYID = 'Admg'
private constant integer ORB_BUFFID = 'Bdmg'
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_CHAOS
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_UNIVERSAL
private boolean SystemActive = false
private location ZLoc = null
endglobals
private function DamageCalculation takes unit Source, unit Target, real Damage returns real
local real D
call MoveLocation(ZLoc, GetUnitX(Source), GetUnitY(Source))
set D = GetLocationZ(ZLoc)
call MoveLocation(ZLoc, GetUnitX(Target), GetUnitY(Target))
set D = D-GetLocationZ(ZLoc)
//For every 80 height, the attacker gains 7% damage bonus
return D/80.00*0.07*Damage
endfunction
function AttackHeightAdvantage_Activate takes boolean activate returns nothing
set SystemActive = activate
endfunction
private function OnDamage takes nothing returns boolean
local unit T = GetTriggerUnit()
local unit S = GetEventDamageSource()
if GetUnitAbilityLevel(T, ORB_BUFFID) > 0 and SystemActive and not IsUnitType(S, UNIT_TYPE_STRUCTURE) then
call UnitRemoveAbility(T, ORB_BUFFID)
call DisableDamageDetect()
call UnitDamageTarget(S, T, DamageCalculation(S, T, GetEventDamage()), false, false, ATTACK_TYPE, DAMAGE_TYPE, null)
call EnableDamageDetect()
endif
set T = null
set S = null
return false
endfunction
private function EnterAdd takes nothing returns boolean
local unit U = GetTriggerUnit()
local unit S = GetEventDamageSource()
if not IsUnitType(S, UNIT_TYPE_STRUCTURE) then
call UnitAddAbility(U, ORB_ABILITYID)
call UnitMakeAbilityPermanent(U, true, ORB_ABILITYID)
endif
set U = null
return false
endfunction
private function InitAdd takes nothing returns nothing
local unit U = GetEnumUnit()
if not IsUnitType(U, UNIT_TYPE_STRUCTURE) then
call UnitAddAbility(U, ORB_ABILITYID)
call UnitMakeAbilityPermanent(U, true, ORB_ABILITYID)
endif
set U = null
endfunction
private function Init takes nothing returns nothing
local group G = CreateGroup()
local trigger T = CreateTrigger()
local region R = CreateRegion()
call GroupEnumUnitsInRect(G, bj_mapInitialPlayableArea, BOOLEXPR_TRUE)
call ForGroup(G, function InitAdd)
call DestroyGroup(G)
call RegionAddRect(R, bj_mapInitialPlayableArea)
call TriggerRegisterEnterRegion(T, R, BOOLEXPR_TRUE)
call TriggerAddCondition(T, Condition(function EnterAdd))
set ZLoc = Location(0.00, 0.00)
call AddOnDamageFunc(Condition(function OnDamage))
set G = null
set R = null
endfunction
endlibrary