//TESH.scrollpos=0
//TESH.alwaysfold=0
//*******************************************************************************************
//*
//* Handle Variables Functions
//*
//* -------------------------------
//* Enables the usage of game cache
//* to transphere local variables
//* between functions
//* -------------------------------
//*
//* Requires:
//* ¯¯¯¯¯¯¯¯¯
//* - Global variable with type "Game Cache" and name "cache"
//* Note that this codes MUST BE PLACED BEFORE ANYTHING here.
//**************************************************************************************************
function LocalVars takes nothing returns gamecache
if udg_cache==null then
set udg_cache=InitGameCache("cache")
endif
return udg_cache
endfunction
//-------------------------------------------------
Name | Type | is_array | initial_value |
ActiveBuildsDark | boolean | Yes | |
ActiveBuildsLight | boolean | Yes | |
AgilityHeroes | group | No | |
AI_GoldBonus | integer | No | |
AI_Only_Dark | boolean | No | true |
AI_Only_Light | boolean | No | true |
AI_PlayersDark | force | No | |
AI_PlayersLight | force | No | |
AI_Safes | unit | Yes | |
AI_SafesDark | group | No | |
AI_SafesLight | group | No | |
AI_Workers | unit | Yes | |
AIHeroesDark | group | No | |
AIHeroesLight | group | No | |
AIOnly | boolean | No | |
AIPlayerHeroes | group | No | |
AISpecialHeroes | group | No | |
allAIPlayersDark | force | No | |
allAIPlayersLight | force | No | |
AllHumansSelected | boolean | No | false |
AutomaticPets | boolean | Yes | false |
AxeThrowEffect | effect | No | |
AxeThrowTarget | unit | No | |
Blizzard | weathereffect | No | |
BossDark | unit | No | |
BossItemCount | integer | No | |
BossLight | unit | No | |
BuildingsDark | integer | Yes | 0 |
BuildingsLight | integer | Yes | 0 |
ButtonChallenge | button | No | |
ButtonNormal | button | No | |
cache | gamecache | No | |
CameraRange | real | No | |
CastleLight | location | No | |
ChallengeMode | boolean | No | |
ChallengeTime | real | No | |
ClockRow | integer | No | |
CreepGateClear | boolean | No | |
CreepsComing | boolean | Yes | |
DeadHeroes | group | No | |
DebugMode | boolean | No | false |
DemonGate | location | No | |
DemonLord | unit | No | |
DifficultyChooseOn | boolean | No | |
DwarfAvatar | unit | No | |
EatTree | location | No | |
EvaluationDone | boolean | No | false |
ExperienceGain | real | No | |
Falcon | unit | Yes | |
ForceOfNature | location | No | |
Fountain1 | location | No | |
Fountain2 | location | No | |
FullBuildingsDark | boolean | No | |
FullBuildingsLight | boolean | No | |
FullTowersDark | boolean | No | |
FullTowersLight | boolean | No | |
FullTroopUpgradesDark | boolean | No | |
FullTroopUpgradesLight | boolean | No | |
FullUpgradesDark | boolean | No | false |
FullUpgradesLight | boolean | No | false |
GameEvent | string | No | |
GameplayVoteDialog | dialog | No | |
GameplayVotes | integer | Yes | 0 |
GameTime | timer | No | |
GameTimeMinutes | integer | No | |
GameTimeSeconds | integer | No | |
GazzSpawn | location | No | |
GeneralDark | unit | No | |
GeneralLight | unit | No | |
GripOfDeathEffect | effect | No | |
HelpRequestingHero | unit | No | |
HeroDeadTime | real | No | |
HeroesByPlayerIndex | unit | Yes | |
HeroSelectionTimer | timer | No | |
HeroTestingMode | boolean | No | |
Hint | string | No | |
HuntressLightHasCriticalShot | boolean | No | false |
IntelligenceHeroes | group | No | |
ItemsBosses | itemcode | Yes | |
ItemsNormal | itemcode | Yes | |
LibraryDarkCaption | texttag | No | |
LibraryLightCaption | texttag | No | |
MaxTroops | integer | No | |
MeleeHeroes | group | No | |
Moonfire | location | No | |
MoonfireEffect | effect | No | |
Necromancer | unit | No | |
NormalItemCount | integer | No | |
NumberOfHumanPlayers | integer | No | |
NumberOfHumanPlayersDark | integer | No | |
NumberOfHumanPlayersLight | integer | No | |
OffensiveActive | boolean | No | |
OffensiveTimer | timer | No | |
OffensiveTimerWindow | timerdialog | No | |
OrderStop | ordercode | No | |
PetArray | group | Yes | |
PlayerColors | string | Yes | |
Players | force | No | |
PlayersCount | integer | No | 0 |
PlayersDark | force | No | |
PlayersLight | force | No | |
PlayersScoreSorted | player | Yes | |
PlayingHeroes | group | No | |
RandomInt | integer | No | |
RandomReal | real | No | |
RangedHeroes | group | No | |
Raven | unit | Yes | |
ResearchArray | techcode | Yes | |
ResurrectionTimers | timer | Yes | |
ResurrectionTimersWindows | timerdialog | Yes | |
RetreatLifePercent | real | No | |
Score_Deaths | integer | Yes | |
Score_HeroKills | integer | Yes | |
Score_KillsTotal | integer | Yes | 0 |
Score_StructureKills | integer | Yes | |
ScoreBoardDark | leaderboard | No | |
ScoreBoardLight | leaderboard | No | |
ScoreBoardPositions | integer | Yes | |
ScoreTable | multiboard | No | |
SelectionTimer | timerdialog | No | |
Shop | location | No | |
ShopDark | location | No | |
ShopDarkCaption | texttag | No | |
ShopLight | location | No | |
ShopLightCaption | texttag | No | |
ShrineDark | location | No | |
ShrineLight | location | No | |
SoulDrain1 | location | No | |
SoulDrain2 | location | No | |
SoulDrainEffect | effect | No | |
SpecialRanks | string | Yes | |
SpecialRanksPlayers | player | Yes | |
StandardOfWarOnGround | boolean | No | true |
StrengthHeroes | group | No | |
TempAbilityArrayBloodrage | effect | Yes | |
TempAbilityArrayDemonicConc | effect | Yes | |
TempArea | rect | No | |
TempBool | boolean | No | |
TempInteger | integer | No | 0 |
TempItem | item | No | |
TempPlayer | player | No | |
TempPlayerGroup | force | No | |
TempPoint | location | No | |
TempReal | real | No | |
TempSpecialeffect | effect | Yes | |
TempString | string | No | |
TempTrigger | trigger | No | |
TempUnit | unit | No | |
TempUnit2 | unit | No | |
TempUnitGroup | group | No | |
TempUnitType | unitcode | No | |
TempWorker | unit | No | |
ThrowAxe | effect | No | |
Title | string | No | |
TowerPointsDark | rect | Yes | |
TowerPointsLight | rect | Yes | |
TowersDark | unit | Yes | |
TowersLight | unit | Yes | |
TroopFlipFlopDark | boolean | Yes | |
TroopFlipFlopLight | boolean | Yes | |
UnselectedHeroesDark | group | No | |
UnselectedHeroesLight | group | No | |
UnselectedHeroesLocation | location | No | |
UnselectedPlayersDark | force | No | |
UnselectedPlayersLight | force | No | |
UpgradeBuyer1 | player | No | |
UpgradeBuyer2 | player | No | |
UpgradeNotice | string | No | |
UpgradesCount | integer | No | |
VictoryDark | boolean | No | false |
VictoryLight | boolean | No | false |
Votings | integer | No | |
VotingsNeptun | integer | No | |
WaterElemental | unit | No | |
WaypointArray | location | Yes | |
Weather | weathereffect | No | |
WeatherActive | boolean | No | |
WeatherEffects | weathereffect | Yes |
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Hero_kills_Hero_Conditions takes nothing returns boolean
if ( not ( IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true ) ) then
return false
endif
if ( not ( IsPlayerInForce(GetOwningPlayer(GetKillingUnit()), udg_Players) == true ) ) then
return false
endif
if ( not ( IsPlayerEnemy(GetOwningPlayer(GetKillingUnit()), GetOwningPlayer(GetTriggerUnit())) == true ) ) then
return false
endif
return true
endfunction
function Trig_Hero_kills_Hero_Actions takes nothing returns nothing
local unit killer
local texttag t = CreateTextTag()
local integer i
local string message
local effect e
set killer = udg_HeroesByPlayerIndex[GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit()))]
if ( IsUnitType(killer, UNIT_TYPE_HERO) == true ) then
set e = AddSpecialEffectTarget("Abilities\\Spells\\Human\\ReviveHuman\\ReviveHuman.mdl", killer, "overhead")
call SetHeroStr(killer, GetHeroStr(killer, false)+1, true)
call SetHeroAgi(killer, GetHeroAgi(killer, false)+1, true)
call SetHeroInt(killer, GetHeroInt(killer, false)+1, true)
set i = GetRandomInt(1, 100)
set message = "That was fun!"
if ( i > 10 ) then
set message = "Another one down!"
endif
if ( i > 15 ) then
if ( IsPlayerAlly(GetOwningPlayer(killer), Player(1)) == true ) then
set message = "Evil has been purged!"
else
set message = "I bring darkness!"
endif
endif
if ( i > 20 ) then
if ( IsPlayerAlly(GetOwningPlayer(killer), Player(1)) == true ) then
set message = "For the King!"
else
set message = "Hail to Bolrov!"
endif
endif
if ( i > 25 ) then
if ( IsPlayerAlly(GetOwningPlayer(killer), Player(1)) == true ) then
set message = "I protect these lands!"
else
set message = "Your civilization will fall!"
endif
endif
if ( i > 30 ) then
if ( IsPlayerAlly(GetOwningPlayer(killer), Player(1)) == true ) then
set message = "Judged!"
else
set message = "Terminated!"
endif
endif
if ( i > 35 ) then
set message = "Got one!"
endif
if ( i > 40 ) then
set message = "And stay down!"
endif
if ( i > 45 ) then
set message = "Down to your knees!"
endif
if ( i > 50 ) then
set message = "Too easy.."
endif
if ( i > 55 ) then
set message = "It starts getting fun!"
endif
if ( i >60 ) then
set message = "Take it easy!"
endif
if ( i > 65 ) then
set message = "Don't worry be happy!"
endif
if ( i > 70 ) then
set message = "Anyone seen that kill?"
endif
if ( i > 75 ) then
set message = "Bang!"
endif
if ( i > 80 ) then
set message = "Good fight anyway!"
endif
if ( i > 85 ) then
set message = "Nice try!"
endif
if ( i > 90 ) then
set message = "This is your end!"
endif
if ( i > 95 ) then
set message = "Got Ya!"
endif
set message = ( ( "|cff" + udg_PlayerColors[GetConvertedPlayerId(GetOwningPlayer(killer))] ) + ( message + "|r" ) )
call SetTextTagText(t, message, 0.02)
call SetTextTagPos(t, GetUnitX(killer), GetUnitY(killer), 0.00)
call SetTextTagVelocity(t, 0, 0.03)
call SetTextTagVisibility(t, true)
call SetTextTagFadepoint(t, 3)
call SetTextTagLifespan(t, 4)
call SetTextTagPermanent(t, false)
endif
call DestroyEffect(e)
set e = null
set t = null
set killer = null
endfunction
//===========================================================================
function InitTrig_Hero_kills_Hero takes nothing returns nothing
set gg_trg_Hero_kills_Hero = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Hero_kills_Hero, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition( gg_trg_Hero_kills_Hero, Condition( function Trig_Hero_kills_Hero_Conditions ) )
call TriggerAddAction( gg_trg_Hero_kills_Hero, function Trig_Hero_kills_Hero_Actions )
endfunction
//***************************************************************************
//* *
//* Stomp *
//* *
//* By Blade.dk *
//* *
//* http://www.wc3jass.com/viewforum.php?f=23 *
//* *
//***************************************************************************
//===========================================================================
//Stomp Spell Configuration Section.
constant function StompSpellId takes nothing returns integer
return 'A061' // The rawcode of the Stomp spell.
endfunction
constant function StompDamage takes real level returns real
return 25*level // The damage dealt when the units hits the ground.
endfunction
constant function StompArea takes real level returns real
return 200.00+25.00*level // The spells area of effect.
endfunction
constant function StompHitAllies takes nothing returns boolean
return false // If this is true the spell will affect both allied and enemy units. Otherwise it will affect only enemies.
endfunction
constant function StompDisablePathing takes nothing returns boolean
return false // If this is true the units will be able to pass through units in their way, while being in the air. That looks best, but can cause problems because the units can land at very strange places, even outside the playable map area.
endfunction
constant function StompFlyHeightChangeAllowerId takes nothing returns integer
return 'Amrf' // The rawcode of any "Fly Height Trick". If you haven't changed Medivh's Crow Form spell, just leave this as it is now, and it shouldn't cause problems. However if you've changed that spell, copy/paste it, reset the new one, and put its rawcode here.
endfunction
//===========================================================================
//The spell itself. Don't touch it unless you know exactly what you're doing.
function Trig_Stomp_Conditions takes nothing returns boolean
return GetSpellAbilityId() == StompSpellId()
endfunction
function StompConditions takes nothing returns boolean
if (StompHitAllies()) then
return (not(IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL))) and (GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0) and (GetFilterUnit() != GetTriggerUnit()) and (not(GetHandleBoolean(GetFilterUnit(), "Stomp"))) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)
endif
return (not(IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL))) and (GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0) and (IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(GetTriggerUnit()))) and (not(GetHandleBoolean(GetFilterUnit(), "Stomp"))) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)
endfunction
function StompMove takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit e = GetEnumUnit()
local unit c = GetHandleUnit(t, "caster")
local group g = GetHandleGroup(t, "group")
local location l = Location(GetHandleReal(t, "X"), GetHandleReal(t, "Y"))
local location current = GetUnitLoc(e)
local location new = PolarProjectionBJ(l, DistanceBetweenPoints(l, current)+18, AngleBetweenPoints(l, current))
call SetUnitPositionLoc(e, new)
if (GetHandleBoolean(t, "half")) then
call SetUnitFlyHeight(e, 0, 1800)
endif
if (GetHandleBoolean(t, "end")) then
call SetUnitInvulnerable(e, false)
call UnitDamageTarget(c, e, StompDamage(GetHandleInt(t, "level")), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS) // Just if someone should doubt, ATTACK_TYPE_NORMAL is attack type spells in GUI.
call SetHandleBoolean(e, "Stomp", false)
call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl", new))
if (StompDisablePathing()) then
call SetUnitPathing(e, true)
endif
endif
set t = null
set e = null
set c = null
set g = null
call RemoveLocation(l)
set l = null
call RemoveLocation(new)
set new = null
call RemoveLocation(current)
set current = null
endfunction
function StompLoop takes nothing returns nothing
local timer t = GetExpiredTimer()
local group g = GetHandleGroup(t, "group")
call SetHandleReal(t, "timeelapsed", GetHandleReal(t, "timeelapsed")+0.05)
if (GetHandleReal(t, "timeelapsed") > 0.6) then
call SetHandleBoolean(t, "half", true)
endif
if (GetHandleReal(t, "timeelapsed") > 0.9) then
call SetHandleBoolean(t, "end", true)
endif
call ForGroup(g, function StompMove)
if (GetHandleBoolean(t, "end")) then
call FlushHandleLocals(t)
call DestroyTimer(t)
call DestroyGroup(g)
endif
set t = null
set g = null
endfunction
function StompStart takes nothing returns nothing
local unit e = GetEnumUnit()
local unit c = GetTriggerUnit()
call UnitAddAbility(e, StompFlyHeightChangeAllowerId())
call UnitRemoveAbility(e, StompFlyHeightChangeAllowerId())
call SetUnitFlyHeight(e, 99999999, 1000)
if (StompDisablePathing()) then
call SetUnitPathing(e, false)
endif
call SetUnitInvulnerable(e, true) // Makes the units invulnerable while they're in the air. If they were vulnerabe, they could get attacked, and if they died their corpse would stay in the air, which looks very ugly.
call SetHandleBoolean(e, "Stomp", true) // A boolean used so units won't be affected by multiple stomps, that would drew them in different directions which would suck.
set e = null
set c = null
endfunction
function Trig_Stomp_Actions takes nothing returns nothing
local unit c = GetTriggerUnit()
local location l = GetUnitLoc(c)
local boolexpr be = Condition(function StompConditions)
local integer level = GetUnitAbilityLevel(c, GetSpellAbilityId())
local group g = CreateGroup()
local timer t = CreateTimer()
call GroupEnumUnitsInRangeOfLoc(g, l, StompArea(level), be)
call SetHandleReal(t, "X", GetLocationX(l))
call SetHandleReal(t, "Y", GetLocationY(l))
call SetHandleInt(t, "level", level)
call SetHandleHandle(t, "caster", c)
call SetHandleHandle(t, "group", g)
call ForGroup(g, function StompStart)
call TimerStart(t, 0.05, true, function StompLoop) // Some might call it dumb using 0.05, but it ain't. If you used 0.01 the chance for lag would be 5 times greater, and the difference can't be seen with the human eye.
set c = null // (continued comment) And as there can be many units caught in the AoE it could be really laggy, especially on Battle.net.
call RemoveLocation(l)
set l = null
call DestroyBoolExpr(be)
set be = null
set g = null
set t = null
endfunction
//===========================================================================
function InitTrig_Stomp takes nothing returns nothing
set gg_trg_Stomp = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Stomp, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Stomp, Condition( function Trig_Stomp_Conditions ) )
call TriggerAddAction( gg_trg_Stomp, function Trig_Stomp_Actions )
endfunction
//TESH.scrollpos=83
//TESH.alwaysfold=0
//***************************************************************************************************
//* ===================
//* Jump Template
//* ===================
//* Made by emjlr3.
//* Parabola function by Shadow1500.
//*
//*
//* How to implement:
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* 1. Copy the abilities Jump and Fly Trick to your map.
//*
//* 2. Copy this trigger to your map and the code in the custom script section of this map.
//*
//*
//* Targets/Effects:
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* This is set to all enemy ground units. The target effect can be changed.
//*
//*
//************************************************************************************************
//Variable Configuration:
constant function Jump_Template_SpellId takes nothing returns integer
return 'A056' //Rawcode of the ability being cast
endfunction
constant function Jump_Template_Fly_TrickId takes nothing returns integer
return 'A04Z' //Rawcode of the Fly Trick ability
endfunction
constant function Jump_Template_Target_Damage takes real Level returns real
return 0. + Level * 80. //Target Damage
endfunction
constant function Jump_Template_Target_Area takes real Level returns real
return 200. + Level * 0 //Target Area
endfunction
constant function Jump_Template_Arc takes nothing returns real
return 1.75 //Arc for the jump, a number between 1 and 2 reccomended
endfunction
constant function Jump_Template_Difference takes nothing returns real
return 100. //This is the distance back the unit will land from the target location, so it can look as if the unit is actually slamming their weapon on the target, instead of towards the front of it
endfunction
constant function Jump_Template_Animation1 takes nothing returns string
return "attack slam" //Jump Animation
endfunction
constant function Jump_Template_Animation2 takes nothing returns string
return "stand ready" //End jump Animation
endfunction
constant function Jump_Template_Effect takes nothing returns string
return "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl" //Target effect
endfunction
constant function Jump_Template_Timer_Speed takes nothing returns real
return .01 //Speed of the periodic timer
endfunction
//Spell:
function Jump_Template_Group takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(),bj_groupEnumOwningPlayer) and IsUnitType(GetFilterUnit(),UNIT_TYPE_GROUND)==true
endfunction
function Jump_Template_Damage takes unit u, real r, real x, real y, real r2, boolean attack, boolean ranged, attacktype at, damagetype dt, weapontype wt returns nothing
local group g = CreateGroup()
local boolexpr b = Condition(function Jump_Template_Group)
local unit v
set bj_groupEnumOwningPlayer = GetOwningPlayer(u)
call GroupEnumUnitsInRange(g, x, y, r, b)
call DestroyBoolExpr(b)
loop
set v = FirstOfGroup(g)
exitwhen v == null
call GroupRemoveUnit(g,v)
call UnitDamageTarget(u,v,r2,attack,ranged,at,dt,wt)
endloop
call DestroyGroup(g)
set g = null
set b = null
endfunction
function Jump_Template_Parabola takes real dist, real maxdist,real curve returns real
local real t = (dist*2)/maxdist-1
return (-t*t+1)*(maxdist/curve)
endfunction
function Jump_Template_Move takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit u = GetHandleUnit(t,"u")
local real maxdist = GetHandleReal(t,"maxdist")
local real ang = GetHandleReal(t,"ang")
local real movedist = GetHandleReal(t,"movedist")
local real x = GetHandleReal(t,"x")
local real y = GetHandleReal(t,"y")
local real dist = SquareRoot((GetUnitX(u)-x)*(GetUnitX(u)-x) + (GetUnitY(u)-y)*(GetUnitY(u)-y))
local real height = Jump_Template_Parabola(dist,maxdist,Jump_Template_Arc())
local integer i = GetHandleInt(t,"i")
local integer level = GetHandleInt(t,"level")
call SetUnitPosition(u, GetUnitX(u) + movedist * Cos(ang * bj_DEGTORAD) , GetUnitY(u) + movedist * Sin(ang * bj_DEGTORAD))
call SetUnitFlyHeight(u,height,0)
call SetHandleInt(t,"i",i + 1)
if i == 50 then
call SetUnitTimeScalePercent(u, 100)
elseif i == 100 then
call PauseTimer(t)
call FlushHandleLocals(t)
call DestroyTimer(t)
call PauseUnit( u,false )
call SetUnitPathing( u, true )
call SetUnitFlyHeight(u,GetUnitDefaultFlyHeight(u),9999)
set x = GetUnitX(u) + Jump_Template_Difference() * Cos(ang * bj_DEGTORAD)
set y = GetUnitY(u) + Jump_Template_Difference() * Sin(ang * bj_DEGTORAD)
call DestroyEffect(AddSpecialEffect(Jump_Template_Effect(), x,y))
call Jump_Template_Damage(u, Jump_Template_Target_Area(level), x, y, Jump_Template_Target_Damage(level), false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, null)
call QueueUnitAnimation(u, Jump_Template_Animation2())
endif
set t = null
set u = null
endfunction
function Jump_Template_Actions takes nothing returns nothing
local timer t = CreateTimer()
local unit u = GetTriggerUnit()
local integer level = GetUnitAbilityLevel(u, Jump_Template_SpellId())
local real ux = GetUnitX(u)
local real uy = GetUnitY(u)
local location l = GetSpellTargetLoc()
local real ang = bj_RADTODEG * Atan2((GetLocationY(l)-uy),(GetLocationX(l)-ux))
local real x = GetLocationX(l) - Jump_Template_Difference() * Cos(ang * bj_DEGTORAD)
local real y = GetLocationY(l) - Jump_Template_Difference() * Sin(ang * bj_DEGTORAD)
call SetHandleHandle(t,"u",u)
call SetHandleReal(t,"x",x)
call SetHandleReal(t,"y",y)
call SetHandleReal(t,"maxdist", SquareRoot((ux-x)*(ux-x) + (uy-y)*(uy-y)))
call SetHandleReal(t,"ang",ang)
call SetHandleReal(t,"movedist",SquareRoot((ux-x)*(ux-x) + (uy-y)*(uy-y))/100)
call SetHandleInt(t,"i",0)
call SetHandleInt(t,"level",level)
call PauseUnit( u,true )
call SetUnitPathing( u, false )
call UnitAddAbility( u,Jump_Template_Fly_TrickId() )
call UnitRemoveAbility( u,Jump_Template_Fly_TrickId() )
call SetUnitAnimation(u, Jump_Template_Animation1())
call SetUnitTimeScalePercent(u, 30)
call TimerStart(t,Jump_Template_Timer_Speed(),true,function Jump_Template_Move)
set t = null
set u = null
call RemoveLocation(l)
set l = null
endfunction
//===========================================================================
function Jump_Template_Conditions takes nothing returns boolean
return GetSpellAbilityId() == Jump_Template_SpellId()
endfunction
function InitTrig_Jump_Template takes nothing returns nothing
set gg_trg_Jump_Template = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Jump_Template, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Jump_Template, Condition( function Jump_Template_Conditions ) )
call TriggerAddAction( gg_trg_Jump_Template, function Jump_Template_Actions )
endfunction
//***************************************************************************************************
//*
//* Spider's Web v1.1 by mems
//*
//* ---------------------------------------
//* Makes a spider model unit create a big
//* web around itself. After this spider catch
//* nearby enemy units by throwing webs and
//* pulling them inside to its main web which
//* deals demage per second to its victims.
//* ---------------------------------------
//*
//* Requires:
//* ¯¯¯¯¯¯¯¯¯
//* - Object Editor - A hero with a spider model
//* - Object Editor - The Spider's Web ability
//* - Object Editor - Unit Web (special)
//* - Object Editor - Non modified (original) version of "Unit - Crow Form" ability (if you did not edit the orginal version of crow from ability in your map ignore this)
//* - Trigger Editor - This Trigger
//* - Trigger Editor - Handle Variable Functions at header of this map (Click on map name above)
//* make sure the Configuration Section is pointing to the right ability rawcodes)
//*
//* Effects Used:
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯
//* - Web Air Target used on creating effects, demage effect and catch victim effects
//* - Web Ground Target used on Main Web model
//* - Units Ancient Protectors missle used on land sliding effect
//* - Abilities Crushing Wave effect is used on water sliding effect
//* - Aerial Shackles lightining effect used on catching victim's silk bolt effect
//***************************************************************************************************
//===================================================================================================
// Spider's Web Spell Configuration:
constant function SpidersWeb_SpellId takes nothing returns integer
return 'A04A' //Rawcode of the Spider's Web Ability
endfunction
constant function SpidersWeb_UnitWeb takes nothing returns integer
return 'e00N' //Rawcode of the Unit Web.
endfunction
constant function SpidersWeb_CatchDistance takes integer level returns real
return 600.00+level*200
// This formula adds 100 to spiders victim dedect distance per level.
// Starting from 800 range.
endfunction
constant function SpidersWeb_Duration takes integer level returns real
return 10.00+level*10
// This formula adds 5 seconds to duration of the spell for each level
// Starting from 20 seconds.
endfunction
constant function SpidersWeb_Demage takes integer level returns real
return 50.00+level*50
// This formula adds 10 demage per level
// Starting from 50 demage.
endfunction
constant function SpidersWeb_TargetConditions takes unit Caster, unit Target returns boolean
return (Target != Caster) and ( IsPlayerEnemy(GetOwningPlayer(Target), GetOwningPlayer(Caster)) ) and not(IsUnitType(Target, UNIT_TYPE_STRUCTURE)) and not(IsUnitType(Target,UNIT_TYPE_DEAD)) and not(IsUnitType(Target, UNIT_TYPE_MAGIC_IMMUNE))
//Defines the targetable units with this spell
endfunction
//===================================================================================================
function SpidersWeb_Conditions takes nothing returns boolean
return GetSpellAbilityId() == SpidersWeb_SpellId()
endfunction
//returns the closest unit in given unit group to a given point.
function SpidersWeb_GetClosestUnit takes group g, location P1 returns unit
local unit array Units
local unit PickedUnit = FirstOfGroup(g)
local unit ClosestUnit = PickedUnit
local location P2 = GetUnitLoc(PickedUnit)
local real D1 = DistanceBetweenPoints(P1,P2)
local real D2
local integer n = 0
local integer i = 0
call RemoveLocation(P2)
loop
exitwhen PickedUnit==null
set PickedUnit = FirstOfGroup(g)
set n=n+1
if (PickedUnit!=null)then
set Units[n]=PickedUnit
endif
call GroupRemoveUnit(g,PickedUnit)
set P2 = GetUnitLoc(PickedUnit)
set D2 = DistanceBetweenPoints(P1,P2)
call RemoveLocation(P2)
if (D2<=D1)then
set D1=D2
if (PickedUnit!=null)then
set ClosestUnit = PickedUnit
endif
endif
endloop
loop
exitwhen i==n
set i=i+1
call GroupAddUnit(g,Units[i])
endloop
set i=0
loop
exitwhen i==n
set i=i+1
set Units[i]=null
endloop
return ClosestUnit
endfunction
//Eleminates the Targets from being chought which are already in demage area
function SpidersWeb_UnisIsAvaible takes unit Target, group Small returns boolean
return not (IsUnitInGroup(Target, Small))
endfunction
//Creates web effects near caster and makes unit web visible by time
function SpidersWeb_CreatingEffect takes nothing returns nothing
local timer EffectLoop = GetExpiredTimer()
local unit Caster = H2U(GetHandleHandle(EffectLoop,"Caster"))
local unit Web = H2U(GetHandleHandle(EffectLoop,"Web"))
local real N = GetHandleReal(EffectLoop,"N")
local effect Effect
local location PositionCaster = GetUnitLoc(Caster)
local rect CenteredRegion = RectFromCenterSizeBJ(PositionCaster, 180.00, 100.00 )
local location Point = GetRandomLocInRect( CenteredRegion )
call SetUnitAnimation( Caster, "spell" )
set N = ( N - 3.00)
call SetHandleReal(EffectLoop, "N", N)
set Effect = AddSpecialEffectLoc("Abilities\\Spells\\Undead\\Web\\Web_AirTarget.mdl", Point )
call DestroyEffect( Effect )
call SetUnitVertexColorBJ( Web, 100, 100, 100, N )
call RemoveRect(CenteredRegion)
call RemoveLocation(PositionCaster)
set Caster = null
set Web = null
endfunction
//Stuns and demages units in web when called
function SpidersWeb_DemageUnits takes nothing returns nothing
local timer DemageLoop = GetExpiredTimer()
local unit Caster = H2U(GetHandleHandle(DemageLoop,"Caster"))
local unit PickedUnit
local group UnitGroup
local real CasterFace = GetUnitFacing(Caster)
local location Point = GetUnitLoc(Caster)
local location MainPoint = PolarProjectionBJ(Point, 130.00, ( CasterFace + 180.00 ))
local effect Effect
set UnitGroup = GetUnitsInRangeOfLocAll(200, MainPoint)
set PickedUnit = FirstOfGroup(UnitGroup)
loop
exitwhen PickedUnit==null
set PickedUnit = FirstOfGroup(UnitGroup)
call GroupRemoveUnit(UnitGroup, PickedUnit)
if (SpidersWeb_TargetConditions(Caster, PickedUnit)) then
call SetUnitPathing( PickedUnit, false )
call PauseUnitBJ(true, PickedUnit)
call SetUnitAnimation(PickedUnit, "walk")
set Effect = AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Web\\Web_AirTarget.mdl", PickedUnit, "chest" )
call DestroyEffect( Effect )
call UnitDamageTarget(Caster,PickedUnit,SpidersWeb_Demage(GetUnitAbilityLevel(Caster, SpidersWeb_SpellId())),false,false,null,null,null)
endif
endloop
call RemoveLocation(Point)
call RemoveLocation(MainPoint)
call DestroyGroup(UnitGroup)
set Caster = null
endfunction
//Pulls the targeted unit in web
function SpidersWeb_PullTarget takes nothing returns nothing
local timer CatchEffectLoop = GetExpiredTimer()
local unit Caster = H2U(GetHandleHandle(CatchEffectLoop,"Caster"))
local unit PickedUnit = H2U(GetHandleHandle(CatchEffectLoop,"PickedUnit"))
local lightning WebBolt = H2L(GetHandleHandle(CatchEffectLoop,"WebBolt"))
local effect Effect = H2E(GetHandleHandle(CatchEffectLoop,"Effect"))
local effect MiniEffect
local real CasterFace = GetUnitFacing(Caster)
local real Distance = GetHandleReal(CatchEffectLoop,"Distance")
local real N = GetHandleReal(CatchEffectLoop,"N")
local location Point = GetUnitLoc(Caster)
local location TargetPoint = GetUnitLoc(PickedUnit)
local location MainPoint = PolarProjectionBJ(Point, 130.00, ( CasterFace + 180.00 ))
local location PointToMove
local real Angle = AngleBetweenPoints(MainPoint, TargetPoint)
set N=N+20.00
call SetHandleReal(CatchEffectLoop,"N",N)
set PointToMove = PolarProjectionBJ(TargetPoint, -20.00, Angle)
if not (IsTerrainPathableBJ (TargetPoint, PATHING_TYPE_FLOATABILITY)) then
set MiniEffect = AddSpecialEffectTarget("Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl",PickedUnit,"origin")
else
set MiniEffect = AddSpecialEffectTarget("Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl",PickedUnit,"origin")
endif
call DestroyEffect(MiniEffect)
call SetUnitPositionLocFacingBJ( PickedUnit, PointToMove, Angle )
call MoveLightningEx(WebBolt,false,GetLocationX(TargetPoint),GetLocationY(TargetPoint),GetLocationZ(TargetPoint),GetLocationX(MainPoint),GetLocationY(MainPoint),100 )
if (Distance <= ( N + 50.00 )) then
call DestroyLightning(WebBolt)
call DestroyEffect(Effect)
call PauseTimer(CatchEffectLoop)
call FlushHandleLocals(CatchEffectLoop)
call DestroyTimer(CatchEffectLoop)
endif
call RemoveLocation(Point)
call RemoveLocation(TargetPoint)
call RemoveLocation(MainPoint)
call RemoveLocation(PointToMove)
set Caster = null
set PickedUnit = null
set Effect = null
set WebBolt= null
endfunction
//Dedects a target around web and marks it for pulling into web
function SpidersWeb_FindVictims takes nothing returns nothing
local timer CatchOrderLoop = GetExpiredTimer()
local timer CatchEffectLoop = CreateTimer()
local effect Effect
local lightning WebBolt
local unit Caster = H2U(GetHandleHandle(CatchOrderLoop,"Caster"))
local unit PickedUnit
local boolean myCondition = false
local real CasterFace = GetUnitFacing(Caster)
local real Distance
local location TargetPoint
local location Point = GetUnitLoc(Caster)
local location MainPoint = PolarProjectionBJ(Point, 130.00, ( CasterFace + 180.00 ))
local group UnitGroup
local group Small = GetUnitsInRangeOfLocAll(200, MainPoint)
set UnitGroup = GetUnitsInRangeOfLocAll(SpidersWeb_CatchDistance(GetUnitAbilityLevel(Caster, SpidersWeb_SpellId())), MainPoint)
set PickedUnit = FirstOfGroup(UnitGroup)
loop
exitwhen ((SpidersWeb_TargetConditions(Caster, PickedUnit) and SpidersWeb_UnisIsAvaible(PickedUnit,Small)) or PickedUnit==null)
set PickedUnit = SpidersWeb_GetClosestUnit(UnitGroup,MainPoint)
call GroupRemoveUnit(UnitGroup, PickedUnit)
endloop
if (not (PickedUnit==null)) then
call SetUnitPathing( PickedUnit, false )
call PauseUnitBJ( true, PickedUnit )
set TargetPoint = GetUnitLoc(PickedUnit)
set Effect = AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Web\\Web_AirTarget.mdl", PickedUnit, "chest")
set WebBolt = AddLightningLoc( "LEAS", MainPoint, TargetPoint )
set Distance = DistanceBetweenPoints(MainPoint,TargetPoint)
set CatchEffectLoop = CreateTimer()
call SetLightningColorBJ( WebBolt, 0.50, 1, 0.00, 1.00 )
//Init and run the catching effect loop
call SetHandleHandle(CatchEffectLoop, "Caster", Caster)
call SetHandleHandle(CatchEffectLoop, "PickedUnit", PickedUnit)
call SetHandleHandle(CatchEffectLoop, "Effect", Effect)
call SetHandleHandle(CatchEffectLoop, "WebBolt", WebBolt)
call SetHandleReal(CatchEffectLoop, "Distance", Distance)
call TimerStart(CatchEffectLoop, 0.03, true, function SpidersWeb_PullTarget)
endif
call RemoveLocation(TargetPoint)
call RemoveLocation(Point)
call RemoveLocation(MainPoint)
call DestroyGroup(UnitGroup)
call DestroyGroup(Small)
set WebBolt=null
set Effect = null
set Caster = null
set PickedUnit = null
endfunction
//Changes spiders flying height by time to create a swing effect
function SpidersWeb_SwingEffect takes nothing returns nothing
local timer SpiderEffectLoop = GetExpiredTimer()
local unit Caster = H2U(GetHandleHandle(SpiderEffectLoop,"Caster"))
local integer N = GetHandleInt(SpiderEffectLoop,"N")
if (N==1) then
call SetUnitFlyHeightBJ( Caster, 200.00, 50.00 )
set N=0
call SetHandleInt(SpiderEffectLoop,"N",N)
else
call SetUnitFlyHeightBJ( Caster, 150.00, 50.00 )
set N=1
call SetHandleInt(SpiderEffectLoop,"N",N)
endif
endfunction
function SpidersWeb_Actions takes nothing returns nothing
local timer EffectLoop = CreateTimer()
local timer DemageLoop = CreateTimer()
local timer CatchOrderLoop = CreateTimer()
local timer SpiderEffectLoop = CreateTimer()
local unit Caster = GetSpellAbilityUnit()
local unit Web
local unit PickedUnit
local group UnitGroup
local real Duration = SpidersWeb_Duration(GetUnitAbilityLevel(Caster, SpidersWeb_SpellId()))
local real CatchDistance = SpidersWeb_CatchDistance(GetUnitAbilityLevel(Caster, SpidersWeb_SpellId()))
local real CasterFace = GetUnitFacing(Caster)
local real N = 100.00
local integer N_lopp01 = 4
local real N_lopp02 = 0.00
local location RandomPoint
local location CasterPoint = GetUnitLoc(Caster)
local location MainPoint = PolarProjectionBJ(CasterPoint, 130.00, ( CasterFace + 180.00 ))
local rect RegionCentered = RectFromCenterSizeBJ(MainPoint, 300.00, 300.00)
//Get ready for creating the web
call TriggerSleepAction( 0.2 )
call PauseUnit( Caster, true )
call SetUnitPathing( Caster, false )
call SetUnitInvulnerable( Caster, true )
set Web = CreateUnitAtLoc( GetOwningPlayer(Caster), SpidersWeb_UnitWeb(), MainPoint, 0 )
call SetUnitVertexColorBJ( Web, 100, 100, 100, 100.00 )
//Initiaziation of effect loop
call SetHandleHandle(EffectLoop, "Caster", Caster)
call SetHandleHandle(EffectLoop, "Web", Web)
call SetHandleReal(EffectLoop, "N", N)
//Start Creating effects
call TimerStart(EffectLoop, 0.3, true, function SpidersWeb_CreatingEffect)
call TriggerSleepAction( 2 )
loop
exitwhen N_lopp01==0
set N_lopp01=N_lopp01-1
set RandomPoint = GetRandomLocInRect(RegionCentered)
call SetUnitPositionLoc( Caster, RandomPoint)
call SetUnitFacing(Caster, GetRandomDirectionDeg())
call TriggerSleepAction( 1 )
call RemoveLocation(RandomPoint)
endloop
call RemoveRect(RegionCentered)
call SetUnitPositionLoc( Caster, CasterPoint)
call SetUnitFacing(Caster, CasterFace)
call TriggerSleepAction( 2 )
call PauseTimer(EffectLoop)
call FlushHandleLocals(EffectLoop)
call DestroyTimer(EffectLoop)
call SetUnitAnimation( Caster, "Decay Flesh" )
call SetUnitTimeScalePercent( Caster, 10.00 )
call UnitAddAbilityBJ( 'Amrf', Caster )
call UnitRemoveAbilityBJ( 'Amrf', Caster )
call SetUnitFlyHeightBJ( Caster, 200.00, 200.00 )
call TriggerSleepAction( 0.50 )
call SetUnitInvulnerable( Caster, false )
//Init and start the demage loop
call SetHandleHandle(DemageLoop, "Caster", Caster)
call TimerStart(DemageLoop, 1, true, function SpidersWeb_DemageUnits)
//Init and start CatchOrder loop
call SetHandleHandle(CatchOrderLoop, "Caster", Caster)
call TimerStart(CatchOrderLoop, 3, true, function SpidersWeb_FindVictims)
//Init and start the Swing loop
call SetHandleHandle(SpiderEffectLoop, "Caster", Caster)
call TimerStart(SpiderEffectLoop, 0.7, true, function SpidersWeb_SwingEffect)
//Wait untill duration or spiders death
loop
exitwhen (N_lopp02>=Duration) or (IsUnitType(Caster,UNIT_TYPE_DEAD))
set N_lopp02 = N_lopp02 + 0.4
call TriggerSleepAction(0.2)
endloop
call PauseTimer(SpiderEffectLoop)
call FlushHandleLocals(SpiderEffectLoop)
call DestroyTimer(SpiderEffectLoop)
call PauseTimer(CatchOrderLoop)
call FlushHandleLocals(CatchOrderLoop)
call DestroyTimer(CatchOrderLoop)
call PauseTimer(DemageLoop)
call FlushHandleLocals(DemageLoop)
call DestroyTimer(DemageLoop)
call SetUnitFlyHeightBJ( Caster, 0.00, 200.00 )
call TriggerSleepAction( 0.50 )
call SetUnitTimeScalePercent( Caster, 100.00 )
if not(IsUnitType(Caster,UNIT_TYPE_DEAD)) then
call SetUnitAnimation( Caster, "stand" )
endif
call KillUnit( Web )
call TriggerSleepAction( 0.50 )
call PauseUnit( Caster, false )
call SetUnitPathing( Caster, true )
//reset alive units effected from spell
set UnitGroup = GetUnitsInRangeOfLocAll(400.00, MainPoint)
set PickedUnit = FirstOfGroup(UnitGroup)
loop
exitwhen PickedUnit==null
set PickedUnit = FirstOfGroup(UnitGroup)
call GroupRemoveUnit(UnitGroup, PickedUnit)
if (PickedUnit!=Web and not(IsUnitType(PickedUnit,UNIT_TYPE_DEAD)))then
call SetUnitPathing( PickedUnit, true )
call PauseUnitBJ(false, PickedUnit)
call ResetUnitAnimation( PickedUnit )
endif
endloop
set Caster = null
set Web = null
call RemoveLocation(CasterPoint)
call RemoveLocation(MainPoint)
call DestroyGroup(UnitGroup)
endfunction
//===================================================================================================
function InitTrig_SpidersWeb takes nothing returns nothing
set gg_trg_SpidersWeb = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_SpidersWeb, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_SpidersWeb, Condition( function SpidersWeb_Conditions ) )
call TriggerAddAction( gg_trg_SpidersWeb, function SpidersWeb_Actions )
endfunction
//TESH.scrollpos=27
//TESH.alwaysfold=0
// This is an example showing one way,
// to implent an automatically day/night fading fog with the system
// THIS IS NOT COMPATIBLE WITH THE OTHER TWO EXAMPLES
scope DayNightCycle initializer Init
globals
private constant real TIME_OF_DAY_SPEED = 1.0 // a little timelapse for testing
private boolean dawn = false // help variables, to avoid the 3 times triggering of the GAME_STATE_TIME_OF_DAY event
private boolean dusk = false
endglobals
private function Dawn takes nothing returns nothing
if GetFloatGameState(GAME_STATE_TIME_OF_DAY) == 12 and dawn == false then
call FFS_Change_Fog( FogNoon, 0, 0.1 )
call FFS_Change_Fog( FogMidnight, 240/TIME_OF_DAY_SPEED, 0.1 )
//call DisplayTextToPlayer(GetLocalPlayer(),0,0, "Dawn..")
set dawn = true
set dusk = false
endif
endfunction
private function Dusk takes nothing returns nothing
if GetFloatGameState(GAME_STATE_TIME_OF_DAY) == 0 and dusk == false then
call FFS_Change_Fog( FogMidnight, 0, 0.1 )
call FFS_Change_Fog( FogNoon, 240/TIME_OF_DAY_SPEED, 0.1 )
//call DisplayTextToPlayer(GetLocalPlayer(),0,0, "Dusk..")
set dusk = true
set dawn = false
endif
endfunction
private function Init_Day_Night_Cycle takes nothing returns nothing
// Let's init 2 basic fogs, one for noon time and one for midnight
globals
fog FogNoon
fog FogMidnight
endglobals
// Example #1: (fog for noon time)
set FogNoon = fog.create() // always create structure first!
set FogNoon.name = "Fog for noon time" // just a short description
set FogNoon.start = 2100 // fog starting distance
set FogNoon.end = 2700 // end distance
set FogNoon.density = 1.0 // density
set FogNoon.red = 0.78 // RGB red value (min=0, max=1.0)
set FogNoon.green = 0.84 // RGB green value
set FogNoon.blue = 0.94 // RGB blue value
// Example #1: (fog for midnight time)
set FogMidnight = fog.create()
set FogMidnight.name = "Fog for midnight time"
set FogMidnight.start = 2000
set FogMidnight.end = 2700
set FogMidnight.density = 1.0
set FogMidnight.red = 0.34
set FogMidnight.green = 0.47
set FogMidnight.blue = 0.64
// Set Starting Time
// should be the same time, as your initial fog
call SetFloatGameState(GAME_STATE_TIME_OF_DAY, 12 )
// Let's create a little timelapse for testing
call SetTimeOfDayScale(TIME_OF_DAY_SPEED)
endfunction
//===========================================================================
function Init takes nothing returns nothing
local trigger t = CreateTrigger()
local trigger t2 = CreateTrigger()
local trigger t3 = CreateTrigger()
call TriggerRegisterTimerEvent(t, 0.01, false)
call TriggerAddAction(t, function Init_Day_Night_Cycle)
call TriggerRegisterGameStateEvent(t2, GAME_STATE_TIME_OF_DAY, EQUAL, 12.00)
call TriggerAddAction(t2, function Dawn)
call TriggerRegisterGameStateEvent(t3, GAME_STATE_TIME_OF_DAY, EQUAL, 0.00)
call TriggerAddAction(t3, function Dusk)
endfunction
endscope
//TESH.scrollpos=39
//TESH.alwaysfold=0
// =======================================================================
// FOG FADING SYSTEM | v2.0 | by MoCo, please give credit if you use this)
// =======================================================================
library FFS initializer Init requires TimerUtils
// fog structure
struct fog
string name
real start
real end
real density
real red
real green
real blue
endstruct
globals
private constant integer FOG_STYLE = 0 // 0 = linear, 1 & 2 are expon. functions
// These variables store the current values of the actual active fog
private real fog_start = 0
private real fog_end = 9999
private real fog_density = 0
private real fog_red = -1
private real fog_green = -1
private real fog_blue = -1
// variables used for calculations
private integer fog_fade_ticks
private real fog_fade_amount_start
private real fog_fade_amount_end
private real fog_fade_amount_density
private real fog_fade_amount_red
private real fog_fade_amount_green
private real fog_fade_amount_blue
endglobals
private function FFS_Change_Fog_Callback takes nothing returns nothing
local timer t = GetExpiredTimer()
call SetTimerData(t, GetTimerData(t) - 1 )
set fog_start = fog_start - fog_fade_amount_start
set fog_end = fog_end - fog_fade_amount_end
set fog_density = fog_density - fog_fade_amount_density
set fog_red = fog_red - fog_fade_amount_red
set fog_green = fog_green - fog_fade_amount_green
set fog_blue = fog_blue - fog_fade_amount_blue
call SetTerrainFogEx(FOG_STYLE, fog_start, fog_end, fog_density, fog_red, fog_green, fog_blue)
if GetTimerData(t) <= 0 then
call ReleaseTimer(t)
endif
// Below is a debug display that shows raw values each update tick
// call DisplayTextToPlayer(GetLocalPlayer(),0,0, "FOG - start: "+R2S(fog_start)+", end: "+R2S(fog_end)+", dens: "+R2S(fog_density)+", R: "+R2S(fog_red)+", G: "+R2S(fog_green)+", B: "+R2S(fog_blue))
set t = null
endfunction
function FFS_Change_Fog takes fog NewFog, real fading_duration, real period returns nothing
local timer t
// If no fog active, get color values
if fog_red == -1 and fog_green == -1 and fog_blue == -1 then
set fog_red = NewFog.red
set fog_green = NewFog.green
set fog_blue = NewFog.blue
endif
// if duration 0 or less: instant change
if fading_duration <= 0 then
set fog_start = NewFog.start // Though, we need to update the variables
set fog_end = NewFog.end
set fog_density = NewFog.density
set fog_red = NewFog.red
set fog_green = NewFog.green
set fog_blue = NewFog.blue
call SetTerrainFogEx(FOG_STYLE, fog_start, fog_end, fog_density, fog_red, fog_green, fog_blue)
else
set fog_fade_ticks = R2I( fading_duration / period )
set t = NewTimer()
call SetTimerData(t, fog_fade_ticks)
// Calculate the color amounts to be faded every tick
set fog_fade_amount_start = ( fog_start - NewFog.start ) / fog_fade_ticks
set fog_fade_amount_end = ( fog_end - NewFog.end ) / fog_fade_ticks
set fog_fade_amount_density = ( fog_density - NewFog.density ) / fog_fade_ticks
set fog_fade_amount_red = ( fog_red - NewFog.red ) / fog_fade_ticks
set fog_fade_amount_green = ( fog_green - NewFog.green ) / fog_fade_ticks
set fog_fade_amount_blue = ( fog_blue - NewFog.blue ) / fog_fade_ticks
call TimerStart(t, period, true, function FFS_Change_Fog_Callback)
endif
set t = null
endfunction
private function Start takes nothing returns nothing
// This also might be a good place to create an initial fog
endfunction
//===========================================================================
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterTimerEvent(t, 0.01, false)
call TriggerAddAction(t, function Start)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TimerUtils initializer init
//*********************************************************************
//* TimerUtils (red+blue+orange flavors for 1.24b+)
//* ----------
//*
//* To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//* To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass) More scripts: htt://www.wc3c.net
//*
//* For your timer needs:
//* * Attaching
//* * Recycling (with double-free protection)
//*
//* set t=NewTimer() : Get a timer (alternative to CreateTimer)
//* ReleaseTimer(t) : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2) : Attach value 2 to timer
//* GetTimerData(t) : Get the timer's value.
//* You can assume a timer's value is 0
//* after NewTimer.
//*
//* Multi-flavor:
//* Set USE_HASH_TABLE to true if you don't want to complicate your life.
//*
//* If you like speed and giberish try learning about the other flavors.
//*
//********************************************************************
//================================================================
globals
//How to tweak timer utils:
// USE_HASH_TABLE = true (new blue)
// * SAFEST
// * SLOWEST (though hash tables are kind of fast)
//
// USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = true (orange)
// * kinda safe (except there is a limit in the number of timers)
// * ALMOST FAST
//
// USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = false (red)
// * THE FASTEST (though is only faster than the previous method
// after using the optimizer on the map)
// * THE LEAST SAFE ( you may have to tweak OFSSET manually for it to
// work)
//
private constant boolean USE_HASH_TABLE = true
private constant boolean USE_FLEXIBLE_OFFSET = false
private constant integer OFFSET = 0x100000
private integer VOFFSET = OFFSET
//Timers to preload at map init:
private constant integer QUANTITY = 256
//Changing this to something big will allow you to keep recycling
// timers even when there are already AN INCREDIBLE AMOUNT of timers in
// the stack. But it will make things far slower so that's probably a bad idea...
private constant integer ARRAY_SIZE = 8190
endglobals
//==================================================================================================
globals
private integer array data[ARRAY_SIZE]
private hashtable ht
endglobals
//It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function SetTimerData takes timer t, integer value returns nothing
static if (USE_HASH_TABLE) then
// new blue
call SaveInteger(ht,0,GetHandleId(t), value)
elseif (USE_FLEXIBLE_OFFSET) then
// orange
static if (DEBUG_MODE) then
if (GetHandleId(t)-VOFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
set data[GetHandleId(t)-VOFFSET]=value
else
// new red
static if (DEBUG_MODE) then
if (GetHandleId(t)-OFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
set data[GetHandleId(t)-OFFSET]=value
endif
endfunction
function GetTimerData takes timer t returns integer
static if(USE_HASH_TABLE) then
// new blue
return LoadInteger(ht,0,GetHandleId(t) )
elseif (USE_FLEXIBLE_OFFSET) then
// orange
static if (DEBUG_MODE) then
if(GetHandleId(t)-VOFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
return data[GetHandleId(t)-VOFFSET]
else
// new red
static if (DEBUG_MODE) then
if(GetHandleId(t)-OFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
return data[GetHandleId(t)-OFFSET]
endif
endfunction
//==========================================================================================
globals
private timer array tT[ARRAY_SIZE]
private integer tN = 0
private constant integer HELD=0x28829022
//use a totally random number here, the more improbable someone uses it, the better.
endglobals
//==========================================================================================
function NewTimer takes nothing returns timer
if (tN==0) then
//If this happens then the QUANTITY rule has already been broken, try to fix the
// issue, else fail.
debug call BJDebugMsg("NewTimer: Warning, Exceeding TimerUtils_QUANTITY, make sure all timers are getting recycled correctly")
static if( not USE_HASH_TABLE) then
debug call BJDebugMsg("In case of errors, please increase it accordingly, or set TimerUtils_USE_HASH_TABLE to true")
set tT[0]=CreateTimer()
static if( USE_FLEXIBLE_OFFSET) then
if (GetHandleId(tT[0])-VOFFSET<0) or (GetHandleId(tT[0])-VOFFSET>=ARRAY_SIZE) then
//all right, couldn't fix it
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
return null
endif
else
if (GetHandleId(tT[0])-OFFSET<0) or (GetHandleId(tT[0])-OFFSET>=ARRAY_SIZE) then
//all right, couldn't fix it
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
return null
endif
endif
endif
else
set tN=tN-1
endif
call SetTimerData(tT[tN],0)
return tT[tN]
endfunction
//==========================================================================================
function ReleaseTimer takes timer t returns nothing
if(t==null) then
debug call BJDebugMsg("Warning: attempt to release a null timer")
return
endif
if (tN==ARRAY_SIZE) then
debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")
//stack is full, the map already has much more troubles than the chance of bug
call DestroyTimer(t)
else
call PauseTimer(t)
if(GetTimerData(t)==HELD) then
debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
return
endif
call SetTimerData(t,HELD)
set tT[tN]=t
set tN=tN+1
endif
endfunction
private function init takes nothing returns nothing
local integer i=0
local integer o=-1
local boolean oops = false
static if( USE_HASH_TABLE ) then
set ht = InitHashtable()
loop
exitwhen(i==QUANTITY)
set tT[i]=CreateTimer()
call SetTimerData(tT[i], HELD)
set i=i+1
endloop
set tN = QUANTITY
else
loop
set i=0
loop
exitwhen (i==QUANTITY)
set tT[i] = CreateTimer()
if(i==0) then
set VOFFSET = GetHandleId(tT[i])
static if(USE_FLEXIBLE_OFFSET) then
set o=VOFFSET
else
set o=OFFSET
endif
endif
if (GetHandleId(tT[i])-o>=ARRAY_SIZE) then
exitwhen true
endif
if (GetHandleId(tT[i])-o>=0) then
set i=i+1
endif
endloop
set tN = i
exitwhen(tN == QUANTITY)
set oops = true
exitwhen not USE_FLEXIBLE_OFFSET
debug call BJDebugMsg("TimerUtils_init: Failed a initialization attempt, will try again")
endloop
if(oops) then
static if ( USE_FLEXIBLE_OFFSET) then
debug call BJDebugMsg("The problem has been fixed.")
//If this message doesn't appear then there is so much
//handle id fragmentation that it was impossible to preload
//so many timers and the thread crashed! Therefore this
//debug message is useful.
elseif(DEBUG_MODE) then
call BJDebugMsg("There were problems and the new timer limit is "+I2S(i))
call BJDebugMsg("This is a rare ocurrence, if the timer limit is too low:")
call BJDebugMsg("a) Change USE_FLEXIBLE_OFFSET to true (reduces performance a little)")
call BJDebugMsg("b) or try changing OFFSET to "+I2S(VOFFSET) )
endif
endif
endif
endfunction
endlibrary