Name | Type | is_array | initial_value |
CreepLocs | location | Yes | |
i | integer | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Revive_Conditions takes nothing returns boolean
return GetOwningPlayer(GetTriggerUnit()) == Player(PLAYER_NEUTRAL_AGGRESSIVE)
endfunction
function Trig_Revive_Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local integer i = GetUnitUserData(u)
local integer id = GetUnitTypeId(u)
local real x = GetLocationX(udg_CreepLocs[i])
local real y = GetLocationY(udg_CreepLocs[i])
call TriggerSleepAction(30)
call CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE), id, x, y, GetRandomReal(0, 360))
call SetUnitUserData(u, i)
set u = null
endfunction
//===========================================================================
function InitTrig_Revive takes nothing returns nothing
set gg_trg_Revive = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Revive, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition( gg_trg_Revive, Condition( function Trig_Revive_Conditions ) )
call TriggerAddAction( gg_trg_Revive, function Trig_Revive_Actions )
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
//**************************************************************//
//**************************************************************//
// //
// Poisonous Mushroom //
// by Justify //
// //
//**************************************************************//
//**************************************************************//
// //
// How to import the spell: //
// Copy the spells: //
// Poisonous Mushroom //
// and //
// Detonate //
// Copy the units: //
// Mushroom //
// and //
// MushroomMissle //
// Copy the triggers: //
// Poisonous Mushroom //
// OnLearn //
// and //
// MushroomLibrary //
// //
// into your map and configure them. //
// Please remember to give credits and //
// have fun with it ;) //
// //
//**************************************************************//
//**************************************************************//
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope PoisonousMushroom
//Allows to put the global arrays before the struct (compile error without it)
private keyword MushroomStruct
private keyword MushroomMissleStruct
globals
//-------------------------------------------------------------------------------
//DON'T CHANGE ANYTHING OVER THIS LINE UNLESS YOU WANT TO CHANGE THE SPELL ITSELF
//-------------------------------------------------------------------------------
//You can find these IDs in the object editor by pressing CTRL+D
private constant integer MushroomSpellID = 'A000' //Poisonous Mushroom (Spell)
private constant integer DetonateSpellID = 'A001' //Detonate (Spell)
private constant integer MushroomUnitID = 'h000' //Mushroom (Unit)
private constant integer MushroomMissleID = 'h001' //MushroomMissle (Unit), only important if MisslesBetweenExplosion = true
//Settings for the spell
private constant real GrowthTime = 30 //Growth time
private constant real MaxSize = 2.5 //Maximum size of growing mushrooms, 2.5 is nearly as big as normal trees.
private constant real AreaOfEffectBase = 200 //Base area of effect
private constant real AreaOfEffectAdd = 10 //Area of effect bonus per second
private constant real AreaBaseLevelMultiplier = 0 //Base area + base area * multiplier*(skill level -1) = new base area, for example level 2: 400+1*400*(2-1) = 800, while it is still 400 with 0 as multiplier
private constant real AreaAddLevelMultiplier = 0.5 //Same math then AreaBaseLevelMultiplier but for the area added per second
private constant real DamageBase = 0 //Base damage
private constant real DamageAdd = 10 //Bonus damage per second
private constant real DamageBaseLevelMultiplier = 0 //AreaBaseLevelMultiplier...
private constant real DamageAddLevelMultiplier = 0.5 //AreaAddLevelMultiplier...
private constant real MinDistance = 300 //Minimum distance between two mushrooms
private constant boolean ChainExplosion = true //Should an exploding mushrooms trigger other ones?
private constant real ExplosionDelay = 0.5 //Delay between exploding mushrooms, if 0 the MisslesBetweenExplosion won't work!
private constant real MaxChainDistance = 1000 //Maximum distance between two mushrooms for exploding per chainreaction
private constant real MaxDetonateDistance = 1000 //Maximum distance for detonate
private constant integer MaxMushrooms = 10 //The maximum number of mushrooms at the same time
private constant boolean NewExplodesOld = true //Should the 1. mushroom explode if to many are placed?
private constant boolean ExplodeAfterTime = false //Should the mushroom explode automaticly after the GrowthTime?
private constant boolean MisslesBetweenExplosion = true //Activates a missle, flying between caster/explosions
//Sfx
private constant string CasterArtPlace = "Abilities\\Spells\\NightElf\\ManaBurn\\ManaBurnTarget.mdl" //Caster animation while placing the mushroom
private constant string CasterArtPlaceAttach = "origin" //Attachment point for CasterArtPlace
private constant string ExplodeArtMushroom = "Abilities\\Weapons\\ChimaeraAcidMissile\\ChimaeraAcidMissile.mdl" //Effect of the mushroom explosion
//--------------------------------------------------------------------------------
//DON'T CHANGE ANYTHING UNDER THIS LINE UNLESS YOU WANT TO CHANGE THE SPELL ITSELF
//--------------------------------------------------------------------------------
//Globals for the spell
private MushroomStruct array MushroomData
private MushroomMissleStruct array MushroomMissleData
private timer MushroomTimer = CreateTimer()
private integer MushroomCount = 0
private integer MushroomMissleCount = 0
private player TempOwner = null
endglobals
//Struct for the mushrooms itself
private struct MushroomStruct
unit mushroom
unit caster
integer skilllevel
real duration
boolean growing
endstruct
//Struct for the flying missles between exploding mushrooms
private struct MushroomMissleStruct
unit missle
real dist
real speed
real cos
real sin
real tx
real ty
endstruct
//Code for the detonation
private function DetonateConditions takes nothing returns boolean
return GetSpellAbilityId() == DetonateSpellID
endfunction
//Only targets living non-building enemys
private function ExplodeEnemyDetection takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(), TempOwner) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) and GetWidgetLife(GetFilterUnit())>0.405
endfunction
//Search for the nearest mushroom. Get every mushroom of the same caster and compare the distances
private function GetNearestOwnedMushroom takes real x, real y, real distance, unit caster returns MushroomStruct
local MushroomStruct data
local integer i = 0
local real dx = 0
local real dy = 0
local real dist = 0
local real mindist = distance
local integer mindistid = MaxMushrooms+1
loop
exitwhen i >= MushroomCount
set data = MushroomData[i]
if data.caster == caster then
set dx = GetUnitX(data.mushroom)-x
set dy = GetUnitY(data.mushroom)-y
set dist = SquareRoot(dx*dx+dy*dy)
if dist < mindist then
set mindist = dist
set mindistid = i
endif
endif
set i = i+1
endloop
return mindistid
//mindistid can NEVER reach MaxMushrooms+1, so returning it
//shows if you found something or not (you also could use -1)
endfunction
//Let the mushrooms explode ;)
private function ExplodeMushroom takes integer MushroomCountID, real Delay, real sx, real sy returns nothing
local integer i = MushroomCountID
local integer j = 0
local MushroomStruct data = MushroomData[i]
local MushroomMissleStruct data2 = 0
local real mx = GetUnitX(data.mushroom)
local real my = GetUnitY(data.mushroom)
local real x = 0
local real y = 0
local real aoe = AreaOfEffectBase*(1+(data.skilllevel-1)*AreaBaseLevelMultiplier)+AreaOfEffectAdd*data.duration*(1+(data.skilllevel-1)*AreaAddLevelMultiplier)
local real damage = DamageBase*(1+(data.skilllevel-1)*DamageBaseLevelMultiplier)+DamageAdd*data.duration*(1+(data.skilllevel-1)*DamageAddLevelMultiplier)
local real artperring = 0
local real rings = aoe/100
local real dist = 0
local real angle = 0
local group g = CreateGroup()
local unit u = null
local unit c = data.caster
local player p = GetOwningPlayer(c)
//If activated, create the small flying missle
if MisslesBetweenExplosion and Delay > 0 then
set data2 = MushroomMissleStruct.create()
set data2.missle = CreateUnit(p, MushroomMissleID, sx, sy, GetRandomReal(0, 360))
set x = mx-sx
set y = my-sy
set data2.dist = SquareRoot(x*x+y*y)
set data2.speed = data2.dist/(Delay/0.025)
set angle = Atan2(sy-my, sx-mx)
set data2.cos = Cos(angle)
set data2.sin = Sin(angle)
set data2.tx = mx
set data2.ty = my
set MushroomMissleData[MushroomMissleCount] = data2
set MushroomMissleCount = MushroomMissleCount+1
endif
call TriggerSleepAction(Delay)
loop
exitwhen i >= MaxMushrooms
set MushroomData[i] = MushroomData[i+1]
set i = i+1
endloop
//The callback doesn't accept parameters, you need a global
set TempOwner = GetOwningPlayer(data.mushroom)
call GroupEnumUnitsInRange(g, mx, my, aoe, Condition(function ExplodeEnemyDetection))
call RemoveUnit(data.mushroom)
call data.destroy()
set MushroomCount = MushroomCount-1
if MushroomCount == 0 then
call PauseTimer(MushroomTimer)
endif
set i = 1
loop
exitwhen i >= rings
set dist = i*100
set artperring = 4+i
loop
exitwhen j >= artperring
set x = mx+dist*Cos((360/artperring)*j*bj_DEGTORAD)
set y = my+dist*Sin((360/artperring)*j*bj_DEGTORAD)
call DestroyEffect(AddSpecialEffect(ExplodeArtMushroom, x, y))
set j = j+1
endloop
set j = 0
set i = i+1
endloop
loop
set u = FirstOfGroup(g)
exitwhen u == null
call UnitDamageTarget(data.mushroom, u, damage, false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_POISON, WEAPON_TYPE_WHOKNOWS)
call GroupRemoveUnit(g, u)
endloop
call DestroyGroup(g)
set g = null
if ChainExplosion then
set i = GetNearestOwnedMushroom(mx, my, MaxChainDistance, c)
if i != MaxMushrooms+1 then //Remember that i can NEVER be MaxMushrooms+1 if you found a mushroom ;)
call ExplodeMushroom(i, ExplosionDelay, mx, my)
endif
endif
set c = null
endfunction
private function Detonate takes nothing returns nothing
local unit u = GetTriggerUnit()
local real ux = GetUnitX(u)
local real uy = GetUnitY(u)
local integer i = GetNearestOwnedMushroom(ux, uy, MaxDetonateDistance, u)
if i != MaxMushrooms+1 then //Did I mentioned that...^^
call ExplodeMushroom(i, ExplosionDelay,ux, uy)
endif
set u = null
endfunction
//Code for the mushroom
private function PlaceConditions takes nothing returns boolean
return GetSpellAbilityId() == MushroomSpellID
endfunction
private function GrowMushroom takes nothing returns nothing
local MushroomStruct data = 0
local MushroomMissleStruct data2 = 0
local integer i = 0
local real temp
//Move the missles
loop
exitwhen i >= MushroomMissleCount
set data2 = MushroomMissleData[i]
set data2.dist = data2.dist-data2.speed
if data2.dist > 0 then
call SetUnitXY(data2.missle, data2.tx+data2.dist*data2.cos, data2.ty+data2.dist*data2.sin)
else
call KillUnit(data2.missle)
set MushroomMissleData[i] = MushroomMissleData[MushroomMissleCount]
set MushroomMissleCount = MushroomMissleCount-1
call data2.destroy()
endif
set i = i+1
endloop
set i = 0
//Let the mushrooms grow
loop
exitwhen i >= MushroomCount
set data = MushroomData[i]
if data.growing then
set data.duration = data.duration+0.025
set temp = data.duration/GrowthTime*MaxSize
call SetUnitScale(data.mushroom, temp, temp, temp)
//Reached MaxSize
if temp >= MaxSize then
set data.growing = false
//Should explode at MaxSize
if ExplodeAfterTime then
call ExplodeMushroom(i, 0, 0, 0)
endif
endif
endif
set i = i+1
endloop
endfunction
private function PoisonousMushroom takes nothing returns nothing
local unit caster = GetTriggerUnit()
local player owner = GetOwningPlayer(caster)
local real lx = GetSpellTargetX()
local real ly = GetSpellTargetY()
local real dx = 0
local real dy = 0
local real dist = 0
local integer i = 0
local MushroomStruct data
//Check for the MinDistance
set i = GetNearestOwnedMushroom(lx, ly, MinDistance, caster)
if i != MaxMushrooms+1 then
call IssueImmediateOrder(caster, "stop" )
call DisplayTextToPlayer(owner, 0, 0, "|cffffcc00There is already an other Poisonous Mushroom near the target point.|r")
set caster = null
return
endif
//11. Mushroom (or MaxMushroom+1)
if MushroomCount >= MaxMushrooms-1 then
if NewExplodesOld then
call ExplodeMushroom(0, ExplosionDelay, GetUnitX(caster), GetUnitY(caster))
else
call IssueImmediateOrder(caster, "stop" )
call DisplayTextToPlayer(owner, 0, 0, "|cffffcc00There are already "+I2S(MaxMushrooms)+" Poisonous Mushrooms at the map.|r")
set caster = null
return
endif
endif
call DestroyEffect(AddSpecialEffectTarget(CasterArtPlace, caster, CasterArtPlaceAttach))
set data = MushroomStruct.create()
set data.mushroom = CreateUnit(owner, MushroomUnitID, lx, ly, GetRandomReal(0, 360))
set data.duration = 0
set data.growing = true
set data.skilllevel = GetUnitAbilityLevel(caster, MushroomSpellID)
set data.caster = caster
call SetUnitScale(data.mushroom, 0, 0, 0)
if MushroomCount == 0 then
call TimerStart(MushroomTimer, 0.025, true, function GrowMushroom)
endif
set MushroomData[MushroomCount] = data
set MushroomCount = MushroomCount+1
set caster = null
endfunction
//===========================================================================
function InitTrig_Poisonous_Mushroom takes nothing returns nothing
local trigger place = CreateTrigger()
local trigger detonate = CreateTrigger()
local integer i = 0
loop
exitwhen i >= bj_MAX_PLAYER_SLOTS
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
call TriggerRegisterPlayerUnitEvent(place, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
call TriggerRegisterPlayerUnitEvent(detonate, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
endif
set i = i+1
endloop
call TriggerAddCondition(place, Condition(function PlaceConditions))
call TriggerAddCondition(detonate, Condition(function DetonateConditions))
call TriggerAddAction(place, function PoisonousMushroom)
call TriggerAddAction(detonate, function Detonate)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MushroomLib
function SetUnitXY takes unit u, real x, real y returns nothing
local real minx = GetRectMinX(bj_mapInitialPlayableArea)
local real maxx = GetRectMaxX(bj_mapInitialPlayableArea)
local real miny = GetRectMinY(bj_mapInitialPlayableArea)
local real maxy = GetRectMaxY(bj_mapInitialPlayableArea)
if (x < minx) then
call SetUnitX(u, minx)
elseif (x > maxx) then
call SetUnitX(u, maxx)
else
call SetUnitX(u, x)
endif
if (y < miny) then
call SetUnitY (u, miny)
elseif (y > maxy) then
call SetUnitY (u, maxy)
else
call SetUnitY (u, y)
endif
endfunction
endlibrary