Name | Type | is_array | initial_value |
//TESH.scrollpos=22
//TESH.alwaysfold=0
scope Glob initializer init
globals
constant integer RAVEN = 'Amrf'
constant integer GARN = 'Abun'
constant integer ERRE = 'Awan'
boolean array Military [12]
boolean array Pirate [12]
boolean array Merchant [12]
boolean array Terrorist [12]
boolean array Alien [12]
boolean CreepsEnabled
integer SOUND_GOLD
unit array Freeport [16]
constant integer MAXPLAYER = 11
string array PlayerColor [12]
endglobals
private function AddRaven takes nothing returns boolean
local unit enteringUnit = GetTriggerUnit()
if GetUnitAbilityLevel(enteringUnit,RAVEN)<= 0 then
call UnitAddAbility(enteringUnit,RAVEN)
call UnitRemoveAbility(enteringUnit,RAVEN)
else
call UnitRemoveAbility(enteringUnit,RAVEN)
endif
set enteringUnit = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
set PlayerColor[0] = "|c00ff0000"
set PlayerColor[1] = "|c000000ff"
set PlayerColor[2] = "|c0000ffff"
set PlayerColor[3] = "|c00800080"
set PlayerColor[4] = "|c00ffff00"
set PlayerColor[5] = "|c00ff8000"
set PlayerColor[6] = "|c0000ff00"
set PlayerColor[7] = "|c00ff00ff"
set PlayerColor[8] = "|c00AAAAFF"
set PlayerColor[9] = "|c00005500"
set PlayerColor[10] = "|c00B06000"
set PlayerColor[11] = "|c00AAAAAA"
call AbilityPreload(RAVEN)
call AbilityPreload(GARN)
call AbilityPreload(ERRE)
set SOUND_GOLD = DefineSound("Abilities\\Spells\\Other\\Transmute\\AlchemistTransmuteDeath1.wav",1601 , false, true)
call TriggerRegisterEnterRectSimple(t, bj_mapInitialPlayableArea)
call TriggerAddCondition( t, Condition( function AddRaven ) )
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Resource
function SetResource takes player whichPlayer, integer gold, integer lumber returns nothing
call SetPlayerState(whichPlayer, PLAYER_STATE_RESOURCE_GOLD,GetPlayerState(whichPlayer,PLAYER_STATE_RESOURCE_GOLD)+gold)
call SetPlayerState(whichPlayer, PLAYER_STATE_RESOURCE_LUMBER,GetPlayerState(whichPlayer,PLAYER_STATE_RESOURCE_LUMBER)+lumber)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope removeitems initializer init
globals
private constant real TIMEOUT = 15.
endglobals
function FilterItems takes nothing returns boolean
call RemoveItem(GetFilterItem())
return true
endfunction
private function RemoveItemSecurity takes nothing returns nothing
local timer t = GetExpiredTimer()
call EnumItemsInRect(bj_mapInitialPlayableArea,Filter(function FilterItems),null)
endfunction
private function Actions takes nothing returns nothing
local timer t = NewTimer()
call TimerStart (t, TIMEOUT, true, function RemoveItemSecurity )
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterTimerEventSingle(t, 30. )
call TriggerAddAction( t, function Actions )
endfunction
endscope
//TESH.scrollpos=203
//TESH.alwaysfold=0
library creasystemes initializer init needs TextDisplay, RunGameSystem, TimerUtils
globals
integer array SsSunId [3] //Id des unités qui forment les étoiles
integer array SsPlaneteId [8] //Id des différentes planètes
integer array SsNebulaId [5] //Id des nebulas (dummys avec des couleurs flashys)
integer array SsDeadShipId [4] //Id des destructables en forme de vaisseaux détruits
unit DummyAttackerNebula //le dummy qui sert à checker la présence de vaisseaux dans le champ de nebula
unit DummyAttackerPirate //le dummy qui sert à checker la présence de vaisseaux dans le champ de destructables vaisseaux
rect array Quadrant [16] //La carte est divisée en 16 carrés similaires
real array QuadrantX [16] //Centre d'une région
real array QuadrantY [16]
boolean array StartLocationPicked [16] //booléen pour vérifier qu'un secteur est attribué à un joueur
unit array PlanetWithBonusPulsar [50] //pour retrouver pour le système d'income les planètes avec bonus de pulsar (gold)
unit array PlanetWithBonusIron [50] //idem pour l'iron (bois)
integer PlanetWithBonusPulsarMax = 0 //pour avoir le nombre max des planètes en question
integer PlanetWithBonusIronMax = 0
//Planets with bonus
constant integer PLANETINCOMEBONUS_PULSAR ='A00G' //skill qu'une planète avec bonus possède
constant integer PLANETINCOMEBONUS_IRON ='A00H'
//Asteroids data
private constant integer ASTEROID_ID = 'B000' //ID d'un destructable asteroide
private constant integer ASTEROID_AMOUNT_FIELD = 40 //nombre d'asteroides dans le champ d'asteroides
private constant integer ASTEROID_AMOUNT_QUADRANT = 40 //nombre d'asteroides qui séparent certains quadrants
private constant real ASTEROID_RADIUS = 3000. //zone de spawn pour les asteroides
//dead ship data
private constant integer DEADSHIP_AMOUNT_FIELD = 40 //idem pour les destructables vaisseaux
private constant real DEADSHIP_RADIUS = 1000.
//nebula data
private constant integer NEBULA_AMOUNT_FIELD = 80 //idem pour les nebula
private constant real NEBULA_RADIUS = 1000.
//Mine data
private constant integer MINE_SMALL = 'n000' //équivelent de mine d'or
private constant integer MINE_BIG = 'n001'
private constant real MINE_RADIUS = 1500.//zone de spawn des mines
private constant integer MINE_AMOUNT = 4 //nombre de mine/secteur
//misc
private constant integer MAXQUADRANT = 15 //(real number-1) il y a 16 quadrants, mais on part de 0 dans les boucles
private constant real TIMEOUT_SYSTEM = 0.10 //interval de création des quadrants
private constant real TIMEOUT_ASTEROID = 0.01 //interval de création des asteroides
private constant real ORBIT = 500. //radius between stars and orbit circle
private constant integer SOLARSYSTEM_AMOUNT = 14 //nombre de systèmes solaires complets (14 sur les 16 quadrants, le 15 et le 16 sont le champ de nebula et le champ de vaisseaux morts
endglobals
private struct strasteroids
integer i
real x
real y
integer amount
endstruct
//fonction périodique qui créée les asteroides. J'utilise un timer pour diminuer le freeze qui a lieu si je créé tout d'un coup
private function SpawnAsteroids takes nothing returns nothing
local timer t = GetExpiredTimer()
local strasteroids dat = GetTimerData(t)
local real x = dat.x+GetRandomReal(-ASTEROID_RADIUS,ASTEROID_RADIUS)
local real y = dat.y+GetRandomReal(-ASTEROID_RADIUS,ASTEROID_RADIUS)
if dat.i < dat.amount then
set dat.i = dat.i + 1
call CreateDestructable(ASTEROID_ID, x,y,GetRandomReal(0.,360.), GetRandomReal(1., 3.), 1)
else
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
//initialization de la fonction ci-dessus
private function CreateAsteroids takes real x, real y,integer whichAmount returns nothing
local timer t = NewTimer()
local strasteroids dat = strasteroids.create()
set dat.i = 0
set dat.amount = whichAmount
set dat.x = x
set dat.y = y
call SetTimerData(t, dat)
call TimerStart (t, TIMEOUT_ASTEROID, true, function SpawnAsteroids )
endfunction
//Pour créer les champs d'asteroides sur certains quadrants
private function CreateFieldAsteroids takes integer whichQuadrant returns nothing
local real x = GetRectMaxX(Quadrant[whichQuadrant])
local real y = GetRectMaxY(Quadrant[whichQuadrant])
//ASteroids (each inner quadrant xmax/ymax)
call DisplayAllNoSound("Game","please wait... creating secondary asteroids fields for Quadrant "+I2S(whichQuadrant))
call CreateAsteroids(x,y,ASTEROID_AMOUNT_FIELD)
endfunction
//Création du champ de vaisseaux morts
private function CreateFieldPirate takes nothing returns nothing
local integer i = 0
local real x = 0.
local real y = 0.
call DisplayAllNoSound("Game","please wait... creating dead ships field for Quadrant 14")
//Ce dummy attaque toute unité à portée.
//Quand une attaque est détectée, un autre système va créer des unités NEUTRAL_AGRRESIVE
set DummyAttackerPirate = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE),'o010',QuadrantX[14],QuadrantY[14],0.)
//Création des vaisseaux morts
loop
set i = i + 1
exitwhen i > DEADSHIP_AMOUNT_FIELD
set x = QuadrantX[14]+GetRandomReal(-DEADSHIP_RADIUS,DEADSHIP_RADIUS)
set y = QuadrantY[14]+GetRandomReal(-DEADSHIP_RADIUS,DEADSHIP_RADIUS)
call CreateDestructable(SsDeadShipId[GetRandomInt(0,3)], x,y,GetRandomReal(0.,360.),GetRandomReal(0.25,0.5),1)
endloop
endfunction
//Idem pour la Nebula
private function CreateFieldNebula takes nothing returns nothing
local integer i = 0
local real x = 0.
local real y = 0.
local unit nebula
call DisplayAllNoSound("Game","please wait... creating nebula field for Quadrant 15")
//Ce dummy attaque toute unité à portée.
//Quand une attaque est détectée, un autre système va créer un éclair et endommager le vaisseau attaqué
set DummyAttackerNebula = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE),'o00Z',QuadrantX[15],QuadrantY[15],0.)
set i = 0
//Spawn des nebulas
loop
set i = i + 1
exitwhen i > NEBULA_AMOUNT_FIELD
set x = QuadrantX[15]+GetRandomReal(-NEBULA_RADIUS,NEBULA_RADIUS)
set y = QuadrantY[15]+GetRandomReal(-NEBULA_RADIUS,NEBULA_RADIUS)
set nebula = CreateUnit(Player(11),SsNebulaId[GetRandomInt(0,4)],x,y,GetRandomReal(0.,360.))
call SetUnitColor(nebula,GetPlayerColor(Player(GetRandomInt(0,12))))
call SetUnitFlyHeight(nebula, GetRandomReal(0.,300.),0.)
endloop
set nebula = null
endfunction
//Spawn des mines à partir du centre d'un quadrant
private function CreateMine takes real x1, real y1 returns nothing
local integer i = 0
local real x2 = 0.
local real y2 = 0.
//grosse mine: 1 par quadrant "habitable" (tous sauf champ vaisseau mort et nebula)
set x2 = x1+GetRandomReal(-MINE_RADIUS,MINE_RADIUS)
set y2 = y1+GetRandomReal(-MINE_RADIUS,MINE_RADIUS)
call AddResourceAmount(CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),MINE_BIG,x2,y2,GetRandomReal(0.,360.)),32500)
//petite mine: 4 par quadrant "habitable" (tous sauf champ vaisseau mort et nebula)
loop
set i = i + 1
exitwhen i > MINE_AMOUNT
set x2 = x1+GetRandomReal(-MINE_RADIUS,MINE_RADIUS)
set y2 = y1+GetRandomReal(-MINE_RADIUS,MINE_RADIUS)
call AddResourceAmount(CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),MINE_SMALL,x2,y2,GetRandomReal(0.,360.)),12500)
endloop
//On ordonne de créer les asteroides des quadrants une fois les mines créées
call CreateAsteroids(x1,y1,ASTEROID_AMOUNT_QUADRANT)
endfunction
//Pour créer les planètes à partir du centre d'un quadrant
private function CreatePlanete takes real x1, real y1 returns nothing
local integer i = 0
local integer j = 0
local real x2 = 0.
local real y2 = 0.
local real angle = 0
local unit planet = null
//à partir du centre du quadrant
//3 orbites différentes
//3 planètes par orbites
loop
set i = i + 1
exitwhen i > 3
set j = 0
loop
set j = j + 1
exitwhen j > 3
set angle = angle+60.
set x2 = x1+j*ORBIT*Cos(angle)
set y2 = y1+j*ORBIT*Sin(angle)
// création d'une planète
set planet = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),SsPlaneteId[GetRandomInt(0,7)],x2,y2,0.)
//Là on vérifie si la planète est à bonus d'or /bois et on la stocke pour le système d'income
if GetUnitAbilityLevel(planet,PLANETINCOMEBONUS_PULSAR)>= 1 then
set PlanetWithBonusPulsar[PlanetWithBonusPulsarMax]=planet
set PlanetWithBonusPulsarMax = PlanetWithBonusPulsarMax +1
elseif GetUnitAbilityLevel(planet,PLANETINCOMEBONUS_IRON)>= 1 then
set PlanetWithBonusIron[PlanetWithBonusIronMax]=planet
set PlanetWithBonusIronMax = PlanetWithBonusIronMax +1
endif
//On dégage le rallye point de la planète qui ne sert à rien
call UnitRemoveAbility(planet,'ARal')
endloop
endloop
//Une fois les planètes créées, on lance la création des mines du quadrant
call CreateMine(x1,y1)
set planet = null
endfunction
//Pour créer les soleils à partir du centre d'un quadrant
private function SystemCreator takes integer whichQuadrant returns nothing
local unit sun = null
call DisplayAllNoSound("Game","please wait... creating solar system for Quadrant "+ I2S(whichQuadrant))
set sun = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),SsSunId[0],QuadrantX[whichQuadrant],QuadrantY[whichQuadrant],270.)
call CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),SsSunId[1],QuadrantX[whichQuadrant],QuadrantY[whichQuadrant],270.)
call CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),SsSunId[2],QuadrantX[whichQuadrant],QuadrantY[whichQuadrant],270.)
//Une fois les dummys qui forment le soleil créées, on lance les planètes
call CreatePlanete(QuadrantX[whichQuadrant],QuadrantY[whichQuadrant])
set sun = null
endfunction
private struct str
integer i
integer asteroidfield
integer system
endstruct
//Fonction périodique pour éviter de tout créer en même temps, et donc éviter un gros freeze
private function IniCreator takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
//14 systèmes "habitables" + 16 quadrants (les 14 étant compris dans les 16)
if dat.i < SOLARSYSTEM_AMOUNT+MAXQUADRANT then
//Create 12 systems (one per player)+2 empty systems
if dat.system < SOLARSYSTEM_AMOUNT then
call SystemCreator(dat.system)//Création systèmes habitables, 14 en tout
set dat.system = dat.system + 1
elseif dat.i == SOLARSYSTEM_AMOUNT then
call CreateFieldPirate()//création champ de vaisseaux morts
elseif dat.i == MAXQUADRANT+1 then
call CreateFieldNebula()//création champ nebula
elseif dat.i >= MAXQUADRANT+2 and dat.asteroidfield <= MAXQUADRANT then
//Pour tous les quadrants, on créé un champ d'asteroide de sorte que chaque quadrant qui est tangeant par son angle
//à un autre soit séparé par un champ d'asteroide
if dat.asteroidfield!=3 and dat.asteroidfield!=7 and dat.asteroidfield!=11 and dat.asteroidfield!=MAXQUADRANT then
call CreateFieldAsteroids(dat.asteroidfield)
endif
set dat.asteroidfield = dat.asteroidfield + 1
endif
set dat.i = dat.i + 1
else
//Une fois la création complète de la carte terminée, on release le timer
call ReleaseTimer(t)
call dat.destroy()
//Et on peut lancer la partie (autre library)
call RunGame()
endif
endfunction
//Fonction qui permet d'attribuer aléatoirement quel quadrant sera habitable ou non (14 habitables et 2 pour les champs nebula/pirate)
private function SetRandomQuadrant takes nothing returns integer
local integer i = 0
local integer random = 0
loop
exitwhen i > MAXQUADRANT//On s'arrête une fois l'ensemble des secteurs checkés
set random = GetRandomInt(0,MAXQUADRANT) //random
if StartLocationPicked[random]==false then//on regarde si le secteur est déjà pris
set StartLocationPicked[random]=true//on pourra savoir que ce secteur est déjà pris
return random//on renvoie la valeur (l'ID) du quadrant qui va être utilisé
endif
set i = i + 1
endloop
return 16
endfunction
//Première fonction appelée pour la création de la carte
private function StartMapCreation takes nothing returns boolean
local timer t = NewTimer() //Parce que tout va se faire par timer pour éviter les longs freeze
local str dat = str.create()
local integer i = 0
local integer randomquadrant = 0
call SetSkyModel( "Environment\\Sky\\BlizzardSky\\BlizzardSky.mdx" )//Add the sky model
//On enlève tout contrôle aux joueurs et on affiche un écran noir pendant le chargement de la création
call CinematicModeBJ(true, bj_FORCE_ALL_PLAYERS ) //disabled in Start trigger
call CinematicFadeBJ(bj_CINEFADETYPE_FADEOUT,0.,"ReplaceableTextures\\CameraMasks\\White_mask.blp",0,0,0,0)
call DisplayAllNoSound("Game","Map Initialization")
loop
exitwhen i > MAXQUADRANT
call DisplayAllNoSound("Game","please wait... loading Quadrant "+ I2S(i))
set randomquadrant = SetRandomQuadrant()//On attribue les emplacements des quadrants et ce à quoi ils serviront
set QuadrantX[i]=GetRectCenterX(Quadrant[randomquadrant])
set QuadrantY[i]=GetRectCenterY(Quadrant[randomquadrant])
set i = i + 1
endloop
//C'est partit pour la création de l'ensemble des objets de chaque quadrant
set dat.i = 0
set dat.asteroidfield = 0
set dat.system = 0
call SetTimerData(t, dat)
call TimerStart (t, TIMEOUT_SYSTEM, true, function IniCreator )
return false
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
exitwhen i > 15
set StartLocationPicked[i]=false//précaution: par défaut aucun quadrant n'est utilisé
set i = i + 1
endloop
set SsSunId[0] = 'o00G'//variables
set SsSunId[1] = 'o002'
set SsSunId[2] = 'o001'
set SsPlaneteId[0] = 'o004'
set SsPlaneteId[1] = 'o009'
set SsPlaneteId[2] = 'o006'
set SsPlaneteId[3] = 'o003'
set SsPlaneteId[4] = 'o005'
set SsPlaneteId[5] = 'o007'
set SsPlaneteId[6] = 'o008'
set SsPlaneteId[7] = 'o011'
set SsNebulaId[0] = 'o00U'
set SsNebulaId[1] = 'o00W'
set SsNebulaId[2] = 'o00X'
set SsNebulaId[3] = 'o00V'
set SsNebulaId[4] = 'o00Y'
set SsDeadShipId[0] = 'B002'
set SsDeadShipId[1] = 'B003'
set SsDeadShipId[2] = 'B004'
set SsDeadShipId[3] = 'B000'
set Quadrant[0]=Rect(-10000,-10000,-5000,-5000)//La carte est un carré de 16 carrés égaux
set Quadrant[1]=Rect(-5000,-10000,0,-5000)
set Quadrant[2]=Rect(0,-10000,5000,-5000)
set Quadrant[3]=Rect(5000,-10000,10000,-5000)
set Quadrant[4]=Rect(-10000,-5000,-5000,0)
set Quadrant[5]=Rect(-5000,-5000,0,0)
set Quadrant[6]=Rect(0,-5000,5000,0)
set Quadrant[7]=Rect(5000,-5000,10000,0)
set Quadrant[8]=Rect(-10000,0,-5000,5000)
set Quadrant[9]=Rect(-5000,0,0,5000)
set Quadrant[10]=Rect(0,0,5000,5000)
set Quadrant[11]=Rect(5000,0,10000,5000)
set Quadrant[12]=Rect(-10000,5000,-5000,10000)
set Quadrant[13]=Rect(-5000,5000,0,10000)
set Quadrant[14]=Rect(0,5000,5000,10000)
set Quadrant[15]=Rect(5000,5000,10000,10000)
call TriggerRegisterTimerEvent( t, 0.05, false )//Dès le début de la partie on lance les opérations
call TriggerAddCondition( t, Condition( function StartMapCreation ) )
endfunction
endlibrary
//TESH.scrollpos=123
//TESH.alwaysfold=0
library RunGameSystem needs TimerUtils,TextDisplay,Resource, Income, PlayerLeaveDetection, BoardSystem
globals
unit array FirstShip [12] //Le dummy qui va servir à chaque joueur pour régler sa race, son premier vaisseau etc
constant integer DUMMYPICK = 'ZABC' //Id du dummy en question
private constant integer CARGOSLOT = 'R00K' //
endglobals
private function Advert takes nothing returns nothing
call DisplayAll("Game","If you dont know how to play, enter -help")
endfunction
//Fonction qui constate le nombre de vote en faveur de l'activation ou non des modes de jeu.
//Les votes ont lieu dans une autre library.
private function EndVote takes nothing returns nothing
local integer i = 0
local integer amount = 0
loop
exitwhen i > MAXPLAYER
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
set amount = amount + 1
endif
set i = i + 1
endloop
if amount <=1 then
if VotePirate ==1 then
call DisplayAll("Game","Extended Pirate AI |c00005500enabled|r")
set CreepsEnabled = true
call EnablePirateBase()
else
set CreepsEnabled = false
call DisplayAll("Game","Extended Pirate AI |c00AA0000disabled|r")
endif
else
if R2I(VotePirate/amount) >= R2I(0.5* amount) then
call DisplayAll("Game","Extended Pirate AI |c00005500enabled|r")
set CreepsEnabled = true
call EnablePirateBase()
else
set CreepsEnabled = false
call DisplayAll("Game","Extended Pirate AI |c00AA0000disabled|r")
endif
endif
endfunction
//Après la création des systèmes, voici le lancement de la partie
private function StartMap takes nothing returns nothing
local integer i = 0
local real x = 0.
local real y = 0.
local real angle = 0.
//Options générales
call SetFloatGameState(GAME_STATE_TIME_OF_DAY,12.00)
call SetTimeOfDayScale(0.)
call SuspendTimeOfDay(true)
//Aucun endroit ne doit être visible dès lors que l'on n'est plus à cet endroit
call FogModifierStart(CreateFogModifierRect(Player(PLAYER_NEUTRAL_AGGRESSIVE), FOG_OF_WAR_VISIBLE, bj_mapInitialPlayableArea, true, false))
call FogEnable(true)
call FogMaskEnable(true)
//Pas de musique.
call SetMusicVolume(0)
//On vire l'écran noir du système de création et on redonne le contrôle
call CinematicModeBJ(false, GetPlayersAll() ) //Started in System Creator
call CinematicFadeBJ(bj_CINEFADETYPE_FADEIN,0.,"ReplaceableTextures\\CameraMasks\\White_mask.blp",0,0,0,0)
//Blabla
call DisplayAll("Game","Please vote for Pirate AI mode.")
call DisplayAll("Game","Pirate AI Mode will be validated in 30 seconds.")
//Attribution des alliances initiales
loop
exitwhen i > MAXPLAYER
call SetPlayerAllianceStateBJ( Player(0), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(1), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(2), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(3), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(4), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(5), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(6), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(7), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(8), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(9), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(10), Player(i), bj_ALLIANCE_UNALLIED )
call SetPlayerAllianceStateBJ( Player(11), Player(i), bj_ALLIANCE_UNALLIED )
call FogModifierStart(CreateFogModifierRect(Player(i), FOG_OF_WAR_MASKED,bj_mapInitialPlayableArea, true, false))
call FogModifierStart(CreateFogModifierRect(Player(i), FOG_OF_WAR_FOGGED,bj_mapInitialPlayableArea, true, false))
//Réglages initiaux des technologies, ressources etc...par joueur
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
call SetPlayerAbilityAvailable(Player(i),'A046',false)//biologic weapon spellbook
call SetPlayerAbilityAvailable(Player(i),'A01N',false)//hyp spellbook
call SetPlayerAbilityAvailable(Player(i),'A02D',false)//shrapnel spellbook
call SetPlayerAbilityAvailable(Player(i),'A02V',false)//Steal spellbook
call SetPlayerAbilityAvailable(Player(i),'A02X',false)//Selfdestruction spellbooks
call SetPlayerAbilityAvailable(Player(i),'A02Y',false)//Selfdestruction spellbooks
call SetPlayerTechResearched(Player(i),CARGOSLOT,1)//Grants the first level of cargo slots
call SetResource(Player(i),500,50)//Resources
call SetPlayerTechMaxAllowed(Player(i),'h00O',1)//1 freeport max
call SetPlayerTechMaxAllowed(Player(i),'h01I',1)//Max nexus center: 1
call SetPlayerTechMaxAllowed(Player(i),'h006',0)//Max AA turret: 0
call SetPlayerTechMaxAllowed(Player(i),'h004',0)//Max dock mk I: 0
call SetPlayerTechMaxAllowed(Player(i),'h007',0)//Max ion canon: 0
call SetPlayerTechMaxAllowed(Player(i),'h00F',0)//Max warehouse: 0
call SetPlayerTechMaxAllowed(Player(i),'h003',0)//Base
call SetPlayerTechMaxAllowed(Player(i),'h01A',0)//Energy center
call SetPlayerTechMaxAllowed(Player(i),'h014',0)//Structure center
call SetPlayerTechMaxAllowed(Player(i),'h019',0)//Weapon center
call SetPlayerTechMaxAllowed(Player(i),'h01B',0)//production center
call SetPlayerTechMaxAllowed(Player(i),'h002',0)//Shipyard Mark I
call SetPlayerTechMaxAllowed(Player(i),'h011',0)//Shipyard Mark II
call SetPlayerTechMaxAllowed(Player(i),'h012',0)//Shipyard Mark II
call SetPlayerTechMaxAllowed(Player(i),'h001',0)//Station
call SetPlayerTechMaxAllowed(Player(i),'h005',0)//Torp Launcher
call SetPlayerTechMaxAllowed(Player(i),'h00Z',0)//Training Center
call SetPlayerTechMaxAllowed(Player(i),'h010',0)//Turret Base
//Le quadrant de départ d'un joueur
set x = QuadrantX[i]
set y = QuadrantY[i]
//Création du dummy qui permet à chaque joueur de régler ses options de race etc...
set angle = GetRandomReal(0.,360.)
set FirstShip[i]= CreateUnit(Player(i),DUMMYPICK,x+500.*Cos(angle),y+500.*Sin(angle),0.)
//Adds the first vote: creeps AI
call UnitAddAbility(FirstShip[i],CREEPSTRUE)
call UnitAddAbility(FirstShip[i],CREEPSFALSE)
//Select the unit
if Player(i) == GetLocalPlayer() then
call ClearSelection()
call SelectUnit(FirstShip[i],true)
endif
//Ce dummy sert, en fonction des codes chargés (système d'expérience) à donner des bonus d'aura
set RankDummy[i]=CreateUnit(Player(i),RANKDUMMYID,0.,0.,0.)
endif
set i = i + 1
endloop
call RunIncome() //P Income System
call EnablePlayerLeaveDetection() //P Player Leave Detection
call InitializeBoard() //Save/Load: Board
endfunction
private struct str
integer i
endstruct
private function Wait takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
if dat.i < 152 then
if dat.i ==1 then
call StartMap()//Une seconde après création des systèmes, on lance la partie elle même
elseif dat.i==30 then
call EndVote()//30 secondes après, on check les résultats des votes sur les modes de jeu
elseif dat.i==41 or dat.i == 71 or dat.i==111 or dat.i==151 then
call Advert()//Le reste: on fait de la pub sur le système d'aide
endif
set dat.i = dat.i + 1
else
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
//Fonction appelée après la création des systèmes
function RunGame takes nothing returns boolean
local timer t = NewTimer()
local str dat = str.create()
set dat.i = 0//Un timer juste parce que je spamme sur le menu d'aide
call SetTimerData(t, dat)
call TimerStart (t, 1., true, function Wait )
return false
endfunction
endlibrary
//TESH.scrollpos=6
//TESH.alwaysfold=0
library Table
//***************************************************************
//* Table object 3.0
//* ------------
//*
//* set t=Table.create() - instanceates a new table object
//* call t.destroy() - destroys it
//* t[1234567] - Get value for key 1234567
//* (zero if not assigned previously)
//* set t[12341]=32 - Assigning it.
//* call t.flush(12341) - Flushes the stored value, so it
//* doesn't use any more memory
//* t.exists(32) - Was key 32 assigned? Notice
//* that flush() unassigns values.
//* call t.reset() - Flushes the whole contents of the
//* Table.
//*
//* call t.destroy() - Does reset() and also recycles the id.
//*
//* If you use HandleTable instead of Table, it is the same
//* but it uses handles as keys, the same with StringTable.
//*
//* You can use Table on structs' onInit if the struct is
//* placed in a library that requires Table or outside a library.
//*
//* You can also do 2D array syntax if you want to touch
//* mission keys directly, however, since this is shared space
//* you may want to prefix your mission keys accordingly:
//*
//* set Table["thisstring"][ 7 ] = 2
//* set Table["thisstring"][ 5 ] = Table["thisstring"][7]
//*
//***************************************************************
//=============================================================
globals
private constant integer MAX_INSTANCES=8100 //400000
//Feel free to change max instances if necessary, it will only affect allocation
//speed which shouldn't matter that much.
//=========================================================
private hashtable ht
endglobals
private struct GTable[MAX_INSTANCES]
method reset takes nothing returns nothing
call FlushChildHashtable(ht, integer(this) )
endmethod
private method onDestroy takes nothing returns nothing
call this.reset()
endmethod
//=============================================================
// initialize it all.
//
private static method onInit takes nothing returns nothing
set ht = InitHashtable()
endmethod
endstruct
//Hey: Don't instanciate other people's textmacros that you are not supposed to, thanks.
//! textmacro Table__make takes name, type, key
struct $name$ extends GTable
method operator [] takes $type$ key returns integer
return LoadInteger(ht, integer(this), $key$)
endmethod
method operator []= takes $type$ key, integer value returns nothing
call SaveInteger(ht, integer(this) ,$key$, value)
endmethod
method flush takes $type$ key returns nothing
call RemoveSavedInteger(ht, integer(this), $key$)
endmethod
method exists takes $type$ key returns boolean
return HaveSavedInteger( ht, integer(this) ,$key$)
endmethod
static method flush2D takes string firstkey returns nothing
call $name$(- StringHash(firstkey)).reset()
endmethod
static method operator [] takes string firstkey returns $name$
return $name$(- StringHash(firstkey) )
endmethod
endstruct
//! endtextmacro
//! runtextmacro Table__make("Table","integer","key" )
//! runtextmacro Table__make("StringTable","string", "StringHash(key)" )
//! runtextmacro Table__make("HandleTable","handle","GetHandleId(key)" )
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library BoundSentinel initializer init
//*************************************************
//* BoundSentinel
//* ---------------
//* Author: Vexorian
//*
//* Don't leave your units unsupervised, naughty
//* them may try to get out of the map bounds and
//* crash your game.
//*
//* To implement, just get a vJass compiler and
//* copy this library/trigger to your map.
//*
//*************************************************
//==================================================
globals
// High enough so the unit is no longer visible, low enough so the
// game doesn't crash...
//
// I think you need 0.0 or soemthing negative prior to patch 1.22
//
private constant real EXTRA = 500.0
endglobals
//=========================================================================================
globals
private real maxx
private real maxy
private real minx
private real miny
endglobals
//=======================================================================
private function dis takes nothing returns nothing
local unit u=GetTriggerUnit()
local real x=GetUnitX(u)
local real y=GetUnitY(u)
if(x>maxx) then
set x=maxx
elseif(x<minx) then
set x=minx
endif
if(y>maxy) then
set y=maxy
elseif(y<miny) then
set y=miny
endif
call SetUnitX(u,x)
call SetUnitY(u,y)
set u=null
endfunction
private function init takes nothing returns nothing
local trigger t=CreateTrigger()
local region r=CreateRegion()
local rect rc
set minx=GetCameraBoundMinX() - EXTRA
set miny=GetCameraBoundMinY() - EXTRA
set maxx=GetCameraBoundMaxX() + EXTRA
set maxy=GetCameraBoundMaxY() + EXTRA
set rc=Rect(minx,miny,maxx,maxy)
call RegionAddRect(r, rc)
call RemoveRect(rc)
call TriggerRegisterLeaveRegion(t,r, null)
call TriggerAddAction(t, function dis)
//this is not necessary but I'll do it anyway:
set t=null
set r=null
set rc=null
endfunction
endlibrary
//TESH.scrollpos=211
//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 = true
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
//TESH.scrollpos=12
//TESH.alwaysfold=0
library GroupUtils initializer Init requires optional xebasic
//******************************************************************************
//* BY: Rising_Dusk
//*
//* This library is a combination of several features relevant to groups. First
//* and foremost, it contains a group stack that you can access dynamic groups
//* from. It also provides means to refresh groups and clear any shadow
//* references within them. The included boolexprs are there for backwards
//* compatibility with maps that happen to use them. Since the 1.24c patch,
//* null boolexprs used in GroupEnumUnits* calls no longer leak, so there is no
//* performance gain to using the BOOLEXPR_TRUE constant.
//*
//* Instead of creating/destroying groups, we have moved on to recycling them.
//* NewGroup pulls a group from the stack and ReleaseGroup adds it back. Always
//* remember to call ReleaseGroup on a group when you are done using it. If you
//* fail to do so enough times, the stack will overflow and no longer work.
//*
//* GroupRefresh cleans a group of any shadow references which may be clogging
//* its hashtable. If you remove a unit from the game who is a member of a unit
//* group, it will 'effectively' remove the unit from the group, but leave a
//* shadow in its place. Calling GroupRefresh on a group will clean up any
//* shadow references that may exist within it. It is only worth doing this on
//* groups that you plan to have around for awhile.
//*
//* Constants that can be used from the library:
//* [group] ENUM_GROUP As you might expect, this group is good for
//* when you need a group just for enumeration.
//* [boolexpr] BOOLEXPR_TRUE This is a true boolexpr, which is important
//* because a 'null' boolexpr in enumeration
//* calls results in a leak. Use this instead.
//* [boolexpr] BOOLEXPR_FALSE This exists mostly for completeness.
//*
//* This library also includes a simple implementation of a group enumeration
//* call that factors collision of units in a given area of effect. This is
//* particularly useful because GroupEnumUnitsInRange doesn't factor collision.
//*
//* In your map, you can just replace all instances of GroupEnumUnitsInRange
//* with GroupEnumUnitsInArea with identical arguments and your spells will
//* consider all units colliding with the area of effect. After calling this
//* function as you would normally call GroupEnumUnitsInRange, you are free to
//* do anything with the group that you would normally do.
//*
//* If you don't use xebasic in your map, you may edit the MAX_COLLISION_SIZE
//* variable below and the library will use that as the added radius to check.
//* If you use xebasic, however, the script will automatically use xe's
//* collision size variable.
//*
//* You are also able to use GroupUnitsInArea. This function returns all units
//* within the area, no matter what they are, which can be convenient for those
//* instances where you actually want that.
//*
//* Example usage:
//* local group MyGroup = NewGroup()
//* call GroupRefresh(MyGroup)
//* call ReleaseGroup(MyGroup)
//* call GroupEnumUnitsInArea(ENUM_GROUP, x, y, 350., BOOLEXPR_TRUE)
//* call GroupUnitsInArea(ENUM_GROUP, x, y, 350.)
//*
globals
//If you don't have xebasic in your map, this value will be used instead.
//This value corresponds to the max collision size of a unit in your map.
private constant real MAX_COLLISION_SIZE = 197.
//If you are insane and don't care about any of the protection involved in
//this library, but want this script to be really fast, set this to true.
private constant boolean LESS_SAFETY = false
endglobals
globals
//* Constants that are available to the user
group ENUM_GROUP = CreateGroup()
boolexpr BOOLEXPR_TRUE = null
boolexpr BOOLEXPR_FALSE = null
endglobals
globals
//* Hashtable for debug purposes
private hashtable ht = InitHashtable()
//* Temporary references for GroupRefresh
private boolean Flag = false
private group Refr = null
//* Arrays and counter for the group stack
private group array Groups
private integer Count = 0
//* Variables for use with the GroupUnitsInArea function
private real X = 0.
private real Y = 0.
private real R = 0.
private hashtable H = InitHashtable()
endglobals
private function HookDestroyGroup takes group g returns nothing
if g == ENUM_GROUP then
call BJDebugMsg(SCOPE_PREFIX+"Warning: ENUM_GROUP destroyed")
endif
endfunction
debug hook DestroyGroup HookDestroyGroup
private function AddEx takes nothing returns nothing
if Flag then
call GroupClear(Refr)
set Flag = false
endif
call GroupAddUnit(Refr, GetEnumUnit())
endfunction
function GroupRefresh takes group g returns nothing
set Flag = true
set Refr = g
call ForGroup(Refr, function AddEx)
if Flag then
call GroupClear(g)
endif
endfunction
function NewGroup takes nothing returns group
if Count == 0 then
set Groups[0] = CreateGroup()
else
set Count = Count - 1
endif
static if not LESS_SAFETY then
call SaveInteger(ht, 0, GetHandleId(Groups[Count]), 1)
endif
return Groups[Count]
endfunction
function ReleaseGroup takes group g returns boolean
local integer id = GetHandleId(g)
static if LESS_SAFETY then
if g == null then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Null groups cannot be released")
return false
elseif Count == 8191 then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Max groups achieved, destroying group")
call DestroyGroup(g)
return false
endif
else
if g == null then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Null groups cannot be released")
return false
elseif not HaveSavedInteger(ht, 0, id) then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Group not part of stack")
return false
elseif LoadInteger(ht, 0, id) == 2 then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Groups cannot be multiply released")
return false
elseif Count == 8191 then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Max groups achieved, destroying group")
call DestroyGroup(g)
return false
endif
call SaveInteger(ht, 0, id, 2)
endif
call GroupClear(g)
set Groups[Count] = g
set Count = Count + 1
return true
endfunction
private function Filter takes nothing returns boolean
return IsUnitInRangeXY(GetFilterUnit(), X, Y, R)
endfunction
private function HookDestroyBoolExpr takes boolexpr b returns nothing
local integer bid = GetHandleId(b)
if HaveSavedHandle(H, 0, bid) then
//Clear the saved boolexpr
call DestroyBoolExpr(LoadBooleanExprHandle(H, 0, bid))
call RemoveSavedHandle(H, 0, bid)
endif
endfunction
hook DestroyBoolExpr HookDestroyBoolExpr
private constant function GetRadius takes real radius returns real
static if LIBRARY_xebasic then
return radius+XE_MAX_COLLISION_SIZE
else
return radius+MAX_COLLISION_SIZE
endif
endfunction
function GroupEnumUnitsInArea takes group whichGroup, real x, real y, real radius, boolexpr filter returns nothing
local real prevX = X
local real prevY = Y
local real prevR = R
local integer bid = 0
//Set variables to new values
set X = x
set Y = y
set R = radius
if filter == null then
//Adjusts for null boolexprs passed to the function
set filter = Condition(function Filter)
else
//Check for a saved boolexpr
set bid = GetHandleId(filter)
if HaveSavedHandle(H, 0, bid) then
//Set the filter to use to the saved one
set filter = LoadBooleanExprHandle(H, 0, bid)
else
//Create a new And() boolexpr for this filter
set filter = And(Condition(function Filter), filter)
call SaveBooleanExprHandle(H, 0, bid, filter)
endif
endif
//Enumerate, if they want to use the boolexpr, this lets them
call GroupEnumUnitsInRange(whichGroup, x, y, GetRadius(radius), filter)
//Give back original settings so nested enumerations work
set X = prevX
set Y = prevY
set R = prevR
endfunction
function GroupUnitsInArea takes group whichGroup, real x, real y, real radius returns nothing
local real prevX = X
local real prevY = Y
local real prevR = R
//Set variables to new values
set X = x
set Y = y
set R = radius
//Enumerate
call GroupEnumUnitsInRange(whichGroup, x, y, GetRadius(radius), Condition(function Filter))
//Give back original settings so nested enumerations work
set X = prevX
set Y = prevY
set R = prevR
endfunction
private function True takes nothing returns boolean
return true
endfunction
private function False takes nothing returns boolean
return false
endfunction
private function Init takes nothing returns nothing
set BOOLEXPR_TRUE = Condition(function True)
set BOOLEXPR_FALSE = Condition(function False)
endfunction
endlibrary
//TESH.scrollpos=137
//TESH.alwaysfold=0
library GroupFunction uses GroupUtils,knb,LightningSysteme
globals
private constant integer ISMSMOD = 'A03X'
private unit U
private real Radius
private real X
private real Y
private real Amount
private integer Distance
private integer Speed
private boolean WithKnockback
private integer Count
private rect Area
private player Owner
private integer WhichUnitId
endglobals
//Filter the nearby enemy units arround a specific unit
private function FilterNearbyEnemyUnit takes nothing returns boolean
if IsUnitEnemy(GetFilterUnit(),Owner) then
set Count= Count + 1
endif
return true
endfunction
function CountNearbyEnemyUnits takes unit whichUnit, real radius returns integer
set Count = 0
set Owner = GetOwningPlayer(whichUnit)
call GroupEnumUnitsInRange(ENUM_GROUP,GetUnitX(whichUnit),GetUnitY(whichUnit),radius,Filter(function FilterNearbyEnemyUnit))
return Count
endfunction
//Filter the Pirate units in an area arround coordinates
private function FilterPirateUnit takes nothing returns boolean
if GetOwningPlayer(GetFilterUnit())==Player(PLAYER_NEUTRAL_AGGRESSIVE) then
set Count= Count + 1
endif
return true
endfunction
function CountNearbyPirateUnits takes real x, real y, real radius returns integer
set Count = 0
call GroupEnumUnitsInRange(ENUM_GROUP,x,y,radius,Filter(function FilterPirateUnit))
return Count
endfunction
//Count the units of a player
private function FilterAllUnits takes nothing returns boolean
if GetOwningPlayer(GetFilterUnit())==Owner then
set Count= Count + 1
endif
return true
endfunction
function CountUnitsOfPlayer takes player whichPlayer returns integer
set Count = 0
set Owner = whichPlayer
call GroupEnumUnitsOfPlayer(ENUM_GROUP,Owner,Filter(function FilterAllUnits))
return Count
endfunction
//Count the units of a player whith a level higher than a value
private function ImplementCountUnitOfLevel takes nothing returns boolean
if GetOwningPlayer(GetFilterUnit())==Owner and GetUnitLevel(GetFilterUnit())>=WhichUnitId then
set Count= Count + 1
endif
return true
endfunction
function CountUnitsOfLevel takes player whichPlayer,integer level returns integer
set Count = 0
set WhichUnitId = level
set Owner = whichPlayer
call GroupEnumUnitsOfPlayer(ENUM_GROUP,Owner,Filter(function ImplementCountUnitOfLevel))
return Count
endfunction
//Count the living units of a player
private function FilterLivingUnits takes nothing returns boolean
if GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>0 and GetOwningPlayer(GetFilterUnit())==Owner and GetUnitTypeId(GetFilterUnit())==WhichUnitId then
set Count= Count + 1
endif
return true
endfunction
function CountUnitsOfType takes player whichPlayer,integer id returns integer
set Count = 0
set WhichUnitId = id
set Owner = whichPlayer
call GroupEnumUnitsOfPlayer(ENUM_GROUP,Owner,Filter(function FilterLivingUnits))
return Count
endfunction
//Filter the living units of a player and destroy them
private function FilterLivingUnitsAndKillThem takes nothing returns boolean
if GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>0 then
call KillUnit(GetFilterUnit())
endif
return true
endfunction
function KillAllUnitsOfPlayer takes player whichPlayer returns nothing
call GroupEnumUnitsOfPlayer(ENUM_GROUP,whichPlayer,Filter(function FilterLivingUnitsAndKillThem))
endfunction
//Filter the units in the area arround coordinates and damage or/and knockback them
private function FilterAndActionEnnemyUnits takes nothing returns boolean
if IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(U)) and IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD)==false then
if Amount > 0. then
call UnitDamageTarget(U,GetFilterUnit(),Amount,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endif
if WithKnockback == true and IsUnitType(U,UNIT_TYPE_MECHANICAL)==false and IsUnitType(U,UNIT_TYPE_ANCIENT) and IsUnitType(U,UNIT_TYPE_STRUCTURE) and GetUnitAbilityLevel(U,ISMSMOD)<= 0 then
call recul(GetUnitX(U),GetUnitY(U),GetFilterUnit(),Distance,Speed)
endif
endif
return false
endfunction
function UnitDamageEnemies takes unit whichUnit, real radius, real x, real y, real amount returns nothing
set U = whichUnit
set Radius = radius
set X = x
set Y = y
set Amount = amount
set WithKnockback = false
call GroupEnumUnitsInRange(ENUM_GROUP,x,y,radius,Filter(function FilterAndActionEnnemyUnits))
endfunction
function UnitDamageEnemiesKnb takes unit whichUnit, real radius, real x, real y, real amount,integer distance,integer speed returns nothing
set U = whichUnit
set Radius = radius
set X = x
set Y = y
set Amount = amount
set Distance = distance
set Speed = speed
set WithKnockback = true
call GroupEnumUnitsInRange(ENUM_GROUP,x,y,radius,Filter(function FilterAndActionEnnemyUnits))
endfunction
//Damage all units in an AOE
private function FilterAndActionUnits takes nothing returns boolean
if IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD)==false then
call UnitDamageTarget(U,GetFilterUnit(),Amount,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endif
return false
endfunction
function UnitDamageAll takes unit whichUnit, real radius, real x, real y, real amount returns nothing
set U = whichUnit
set Radius = radius
set X = x
set Y = y
set Amount = amount
call GroupEnumUnitsInRange(ENUM_GROUP,x,y,radius,Filter(function FilterAndActionUnits))
endfunction
endlibrary
//TESH.scrollpos=12
//TESH.alwaysfold=0
library knb needs TimerUtils
globals
private constant real TIMEOUT = 0.05
endglobals
private struct str
unit target
real angle
integer distance
integer speed
integer i
endstruct
private function Action takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
local real newX = GetUnitX(dat.target) + dat.speed*Cos(dat.angle)
local real newY = GetUnitY(dat.target) + dat.speed*Sin(dat.angle)
if (dat.i < dat.distance) then
set dat.i = dat.i + 1
call SetUnitPosition(dat.target, newX, newY)
else
call SetUnitPathing(dat.target, true)
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
function recul takes real x, real y, unit target, integer distance, integer speed returns nothing
local timer t = NewTimer()
local str dat = str.create()
call SetUnitPathing( target, false)
set dat.target = target
set dat.angle = Atan2(GetUnitY(target) - y, GetUnitX(target) - x)
set dat.distance = distance/speed
set dat.speed = speed
set dat.i = 0
call SetTimerData(t, dat)
call TimerStart(t, TIMEOUT, true, function Action)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library LightningSysteme needs TimerUtils
//*Simple librairie qui permet de relier deux unités ensemble par un éclair lumineuxà durée déterminée.
//*
//*A utiliser par l'appel de la fonction:
//*
//*function LightningLink takes unit unit1,unit unit2, string LightningString, real duration,real OptOffset returns nothing
//*
//*Explication des variables:
//*
//*unit1 et unit2 sont les deux unités à relier par l'éclair
//*LightningString est le code (exemple "LEAS") de la forme de l'éclair.
//*duration: rentrer ici le nombre de secondes (réel, exemple 7.5 secondes) pendant lequel les deux unités seront reliées.
//*OptOffset1 et OptOffset2: la plupart du temps il convient de relier les unités au niveau de leur centre de gravité. A 0.00, l'éclair sera sur les pieds des unités.Un archer par exemple appréciera une hauteur de 30.00
//*
//*Constantes:
//*
//*La vitesse d'execution du timer peut se régler dans les constantes globales si-dessous. Plus la valeur est faible, plus le mouvement sera fluide-et gourmand en ressources CPU.
//*
//*Codes des différents effets lumineux:
//*
//* "CLPB" Chaine d'éclairs-primaire
//* "CLSB" Chaine d'éclairs-secondaire
//* "MBUR" Brûlure de Mana
//* "CHIM" Attaque éclair
//* "AFOD" Doigt de la mor
//* "HWPB" Vague de soins-primaire
//* "HWSB" Vague de soins-secondaire
//* "MFPB" Mana Flare
//* "DRAB" Drain
//* "DRAL" Drain de vie
//* "DRAM" Drain de mana
//* "FORK" Forked Lightning
//* "SPLK" Lien spirituel
//* "LEAS" Entraves magiques
//=================================================
globals
private constant real TIMEOUT = 0.04
endglobals
//=================================================
private struct LightningStructure
unit unit1 = null
unit unit2 = null
lightning link = null
integer CountInterval = 0
integer MaxInterval = 0
real OptOffset1 = 0.
real OptOffset2 = 0.
endstruct
//=================================================
private function LightningMove takes nothing returns nothing
local timer t = GetExpiredTimer()
local LightningStructure dat = GetTimerData(t)
local real x1 = GetUnitX(dat.unit1)
local real y1 = GetUnitY(dat.unit1)
local real z1 = GetUnitFlyHeight(dat.unit1)+dat.OptOffset1
local real x2 = GetUnitX(dat.unit2)
local real y2 = GetUnitY(dat.unit2)
local real z2 = GetUnitFlyHeight(dat.unit2)+dat.OptOffset2
if dat.CountInterval < dat.MaxInterval and GetUnitState(dat.unit1, UNIT_STATE_LIFE) > 0 and GetUnitState(dat.unit2, UNIT_STATE_LIFE) > 0 then
set dat.CountInterval = dat.CountInterval + 1
call MoveLightningEx(dat.link,true,x1, y1, z1, x2, y2, z2 )
else
call DestroyLightning(dat.link)
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
//=================================================
function LightningLink takes unit unit1,unit unit2, string LightningString, real duration,real OptOffset1,real OptOffset2 returns nothing
local timer t = NewTimer()
local LightningStructure dat = LightningStructure.create()
local real x1 = GetUnitX(unit1)
local real y1 = GetUnitY(unit1)
local real z1 = GetUnitFlyHeight(unit1)
local real x2 = GetUnitX(unit2)
local real y2 = GetUnitY(unit2)
local real z2 = GetUnitFlyHeight(unit2)
set dat.OptOffset1 = OptOffset1
set dat.OptOffset2 = OptOffset2
set dat.unit1 = unit1
set dat.unit2 = unit2
set dat.link = AddLightningEx(LightningString, true, x1, y1, z1+dat.OptOffset1, x2, y2, z2+dat.OptOffset2)
set dat.CountInterval = 0
set dat.MaxInterval = R2I(duration/TIMEOUT)
call SetTimerData(t, dat)
call TimerStart (t, TIMEOUT, true, function LightningMove )
//=================================================
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TextDisplay initializer init needs SoundUtils
globals
integer SOUND_ERROR
integer SOUND_HINT
endglobals
private function init takes nothing returns nothing
set SOUND_ERROR = DefineSound("Sound\\Interface\\Error.wav", 614, false, false)
set SOUND_HINT = DefineSound("Radio.wav", 525, false, false)
endfunction
function ErrorSound takes player whichPlayer returns nothing
call RunSoundForPlayer(SOUND_ERROR,whichPlayer)
endfunction
function DisplayAllNoSound takes string speaker, string text returns nothing
local integer i = 0
loop
exitwhen i > MAXPLAYER
call DisplayTextToPlayer(Player(i),0.,0.,"|c00AFAAFF"+speaker+"|r"+": "+text)
set i = i + 1
endloop
endfunction
function DisplayAll takes string speaker, string text returns nothing
local integer i = 0
call RunSound(SOUND_HINT)
loop
exitwhen i > MAXPLAYER
call DisplayTextToPlayer(Player(i),0.,0.,"|c00AFAAFF"+speaker+"|r"+": "+text)
set i = i + 1
endloop
endfunction
function Text takes unit u,boolean forall, string text returns nothing
local texttag tag = CreateTextTag()
call SetTextTagText(tag, text, 0.025)
call SetTextTagPos(tag, GetUnitX(u) - 10, GetUnitY(u), 50.) // on enlève 10 au x pour centrer à peu prés le tag sur l'unité
call SetTextTagVelocity(tag, 0.0355 * Cos(90.*bj_DEGTORAD), 0.0355 * Sin(90.*bj_DEGTORAD))
call SetTextTagColor(tag, 255, 255, 255,255)
call SetTextTagFadepoint(tag,1.5) // pour que le texte disparaisse en fondu
call SetTextTagLifespan(tag, 2.) // la durée de vie du texte, fondu compris
call SetTextTagPermanent(tag, false)
if forall == false then
if GetOwningPlayer(u)!=GetLocalPlayer() then
call SetTextTagVisibility(tag,false)
endif
endif
set tag = null
endfunction
endlibrary
//TESH.scrollpos=66
//TESH.alwaysfold=0
library JSDialog initializer init
//***************************************************************************************************
//* JSDialog
//* ----------
//* Author: Profet
//*
//*
//*
//*
//* To implement, just get a vJass compiler and
//* copy this library/trigger to your map.
//*
//***************************************************************************************************
//* SETTING CONSTANTS
globals
private constant integer MAX_BUTTONS = 7 // Maximum number of buttons by dialog.
private constant integer CANCEL_HOTKEY = 512 // ASCII number of cancel shortcut (Esc=512).
private constant string CANCEL_STRING = "|cffFF0000< Cancel >|r" // Defaut "cancel" button's text.
endglobals
//===========================================================================
//* FUNCTIONS INTERFACES
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// IFuncDialogBtnAction : <p> Id of the player who clicked the button.
// <dialogUnit> Unit attached to the dialog.
// <dialogInteger> Integer value attached to the dialog.
// <btnInteger> Integer value attached to the clicked button.
//
//===========================================================================
function interface IFuncDialogBtnAction takes integer p, unit dialogUnit, integer dialogInteger, string btnString, integer btnInteger returns nothing
//===========================================================================
//* LIBRARY'S CORE
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//*
//* Do NOT modify without a really good reason !!
//*
//===========================================================================
private keyword s_dialog
globals
private s_dialog array DIALOG
endglobals
private struct s_dialog
// Dialog's members.
private dialog d
private integer p
private trigger t
private integer dialogInteger = 0
private unit dialogUnit = null
// Buttons' members.
private integer btnCount = 0
private button array btnList[MAX_BUTTONS]
private string array btnString[MAX_BUTTONS]
private integer array btnInteger[MAX_BUTTONS]
private IFuncDialogBtnAction array btnFunc[MAX_BUTTONS]
// Constructor.
static method create takes integer p returns s_dialog
local s_dialog this = s_dialog.allocate()
set this.p = p
set this.d = DialogCreate()
set this.t = CreateTrigger()
call TriggerAddAction( this.t, function s_dialog.clicked_Actions )
call TriggerRegisterDialogEvent( this.t, this.d )
return this
endmethod
method clicked takes button btn returns nothing
local integer i=0
loop
exitwhen( i==.btnCount )
if( .btnList[i]==btn )then
if( .btnFunc[i]>0 )then
call .btnFunc[i].evaluate( .p, .dialogUnit, .dialogInteger, .btnString[i], .btnInteger[i] )
endif
return
endif
set i=i+1
endloop
endmethod
// Static trigger action and method.
private static method clicked_Actions takes nothing returns nothing
call DIALOG[GetPlayerId(GetTriggerPlayer())].clicked(GetClickedButton())
endmethod
// .
method Clear takes string title, unit un, integer attachedInt returns nothing
set .dialogUnit = un
set .dialogInteger = attachedInt
call DialogClear(.d)
call DialogSetMessage( .d, title )
set .btnCount = 0
endmethod
// .
method AddButton takes string text, IFuncDialogBtnAction func, integer key, string attachedString, integer attachedInt returns boolean
if( .btnCount<MAX_BUTTONS )then//-1 or (key==CANCEL_HOTKEY and .btnCount<MAX_BUTTONS)
set .btnList[.btnCount] = DialogAddButton( .d, text, key )
set .btnFunc[.btnCount] = func
set .btnString[.btnCount] = attachedString
set .btnInteger[.btnCount] = attachedInt
set .btnCount = .btnCount + 1
return true
endif
return false
endmethod
// .
method Show takes nothing returns nothing
if( .btnCount==0 )then
call .AddButton(CANCEL_STRING,0,CANCEL_HOTKEY,"",0)
endif
call DialogDisplay( Player(.p), .d, true )
endmethod
endstruct
private function init takes nothing returns nothing
local integer i = 0
loop
exitwhen( i==12 )
set DIALOG[i] = s_dialog.create(i)
set i=i+1
endloop
endfunction
//===========================================================================
//* PUBLIC FUNCTIONS
//===========================================================================
// Show the specified player's dialog.
function Show takes integer playerId returns nothing
call DIALOG[playerId].Show()
endfunction
// Remove all buttons from the player's dialog, change it's title and attached values.
function Clear takes integer playerId, string title, unit attachedUnit, integer attachedInt returns nothing
call DIALOG[playerId].Clear( title, attachedUnit, attachedInt )
endfunction
// Add a button to the player's dialog, return FALSE if there are already too many buttons (MAX_BUTTONS) in the dialog.
function AddButton takes integer playerId, string text, IFuncDialogBtnAction func, integer key, string attachedString, integer attachedInt returns boolean
return DIALOG[playerId].AddButton( text, func, key, attachedString, attachedInt )
endfunction
// Return the maximum number of buttons by dialog.
function MaxButtons takes nothing returns integer
return MAX_BUTTONS
endfunction
// Return the default Cancel button string.
function CancelText takes nothing returns string
return CANCEL_STRING
endfunction
// Return the default Cancel button hotkey.
function CancelHotkey takes nothing returns integer
return CANCEL_HOTKEY
endfunction
endlibrary
//TESH.scrollpos=149
//TESH.alwaysfold=0
library IndieSummons initializer Init requires AutoIndex, TimerUtils, Table
//**************************************************************************************************
//*
//* Independant Summons (Code + config)
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* You just need to copy this trigger, notice that these functions do nothing without the other
//* part which has the header functions and you'll also need to call them.
//*
//**************************************************************************************************
// 2010-01-18 (Original system by Vexorian, modified by MoCo):
// - vjassification of system
// - now works with latest patches
//==================================================================================================
// Independant Summons Configuration:
//
globals
private Table SummonIdTab
private unit array Summons[1]
private unit array Masters[1]
private integer N = 0
private constant integer MAX_N = 64
endglobals
private constant function IndieSummon_maxdelay takes nothing returns real
return 2.5 //* The max delay betwen orders issued to the summon
endfunction
private constant function IndieSummon_mindelay takes nothing returns real
return 1.00 //* The min delay betwen orders issued to the summon
endfunction
private constant function IndieSummon_maxdistance takes nothing returns real
return 500.0 //* If the distance betwen the summon and the master is greater than this value,
// The summon will move to the position of the master instead of attack move
endfunction
private constant function IndieSummon_cometomaxdist takes nothing returns real
return 300.0 //* Max distance for issued orders to approach the master
endfunction
private constant function IndieSummon_cometomindist takes nothing returns real
return 100.0 //* Min distance for issued orders to approach the master
endfunction
//==================================================================================================
private function SetSummonId takes unit summon returns integer
set N = N + 1
set SummonIdTab[GetUnitId(summon)] = N
if N > MAX_N then
set N = 0
endif
return SummonIdTab[GetUnitId(summon)]
endfunction
private function GetSummonId takes unit summon returns integer
return SummonIdTab[GetUnitId(summon)]
endfunction
private function IndieSummon_GetMaster takes unit summon returns unit
local integer id = GetSummonId(summon)
return Masters[id]
return null
endfunction
private function IndieSummon_StopAI takes unit summon returns nothing
local integer id = GetSummonId(summon)
set Masters[id] = null
endfunction
private function IndieSummon_Order takes unit summon, unit master returns nothing
local integer o=GetUnitCurrentOrder(summon)
local real tx=GetUnitX(master)
local real ty=GetUnitY(master)
local real angle
local real dist
set dist=Pow(tx-GetUnitX(summon),2) + Pow(ty-GetUnitY(summon),2)
if (dist > (IndieSummon_maxdistance()*IndieSummon_maxdistance()) ) and (o == 0 or o == OrderId("attack") or o == OrderId("move") or o == OrderId("stop") or o==851971) then
call IssuePointOrder(summon, "move", tx,ty)
elseif dist >= (IndieSummon_cometomindist()*IndieSummon_cometomindist()) and (o == 0 or o == 851971) then
set angle = GetRandomReal( GetUnitFacing(master)-80, GetUnitFacing(master)+80)
if (ModuloInteger(GetUnitPointValue(summon),2)==0) then
set angle=angle * bj_DEGTORAD
else
set angle=- angle * bj_DEGTORAD
endif
set dist = GetRandomReal(IndieSummon_cometomindist(), IndieSummon_cometomaxdist() )
set tx=tx+dist*Cos(angle)
set ty=ty+dist*Sin(angle)
if not IssuePointOrder(summon, "attack", tx, ty ) then
call IssuePointOrder(summon, "move", tx, ty )
endif
endif
set summon=null
set master=null
endfunction
private function IndieSummon_AntiSmart_Timer takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer id = GetTimerData(t)
local unit s = Summons[id]
local unit m = Masters[id]
if (GetUnitCurrentOrder(s)!=851971) then
call DestroyTimer(t)
else
call IndieSummon_Order( s, m )
call TimerStart(t,0.1,false,function IndieSummon_AntiSmart_Timer)
endif
set t = null
set s = null
set m = null
endfunction
private function IndieSummon_AntiSmart takes nothing returns nothing
local timer t
local integer id = GetSummonId(GetTriggerUnit())
if (GetIssuedOrderId() == 851971) then
set t=CreateTimer()
call SetTimerData(t, id)
call TimerStart(t,0,false,function IndieSummon_AntiSmart_Timer)
set t=null
endif
endfunction
private function IndieSummon_loop takes integer id returns nothing
local unit summon = Summons[id]
local unit master // = Masters[id]
local trigger smart=CreateTrigger()
local integer n = 0
local triggeraction ac = TriggerAddAction( smart, function IndieSummon_AntiSmart)
call TriggerRegisterUnitEvent( smart, summon, EVENT_UNIT_ISSUED_TARGET_ORDER )
call TriggerRegisterUnitEvent( smart, summon, EVENT_UNIT_ISSUED_POINT_ORDER )
loop
exitwhen (GetWidgetLife(summon)<=0)
set master = Masters[id]
if (master==null) then
exitwhen true
else
call IndieSummon_Order( summon, master)
call PolledWait( GetRandomReal( IndieSummon_mindelay(), IndieSummon_maxdelay() ))
endif
endloop
set Masters[id] = null
call TriggerRemoveAction(smart,ac)
if smart != null then
call DestroyTrigger(smart)
endif
set ac=null
set summon=null
set master=null
set smart=null
endfunction
function IndieSummon_SetMaster takes unit summon, unit master returns nothing
local integer id
set id = SetSummonId(summon)
set Masters[id] = master
set Summons[id] = summon
call IndieSummon_loop.execute(id)
endfunction
//===========================================================================
private function Init takes nothing returns nothing
set SummonIdTab = Table.create()
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library AbilityPreload initializer Init
// Information:
//==============
//
// Preloading removes the noticeable delay the first time an ability is
// loaded in a game. It is suggested that you preload every ability that
// is not already on a unit that is placed on the map or created at init.
//
// How to install PreloadAbility:
//================================
//
// Just copy the script into your map, no further tweaking needed.
//
// How to use PreloadAbility:
//============================
//
// Just call PreloadAbility(abilityid) during an init function. There is no
// point calling it after init, since it will do nothing, and it would not
// be "pre"-loading anyway.
//
//===========================================================================
globals
private boolean InitDone = false
private unit PreloadUnit
endglobals
function AbilityPreload takes integer abilityid returns nothing
if not InitDone then
call BJDebugMsg("AbilityPreload error: Library has not been initialized yet")
return
elseif GetUnitTypeId(PreloadUnit) == 0 then
call BJDebugMsg("AbilityPreload error: Can't preload an ability after initialization")
return
endif
call UnitAddAbility(PreloadUnit, abilityid)
endfunction
//===========================================================================
private function Init takes nothing returns nothing
set PreloadUnit = CreateUnit(Player(15), 'zsmc', 0., 0., 0.)
call UnitApplyTimedLife(PreloadUnit, 0, .001)
call ShowUnit(PreloadUnit, false)
call UnitAddAbility(PreloadUnit, 'Aloc')
set InitDone = true
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library SoundUtils requires Stack, TimerUtils
//******************************************************************************
//* BY: Rising_Dusk
//*
//* Sounds are a very picky datatype in WC3. They have many quirks that one must
//* account for in order to use them, and simply using the internal WE Sound
//* Editor isn't enough because the sounds it makes can't be played multiple
//* times at once. 3-D sounds are also very tricky because there are different
//* WC3 sound options that a user can have activated where certain sounds will
//* or will not work. This library attempts to streamline the handling of sounds
//* so that it is less likely to confuse you or cause problems.
//*
//* The .mp3 format can be used for 3-D sounds, but there is one problem that
//* must be noted. If your computer supports the "Dolby Surround" sound option
//* in WC3 and you have it selected, then .mp3 files will work for 3-D sounds.
//* If you don't, however, they may not work depending on what you do have
//* selected and what is available for your computer. The .wav format works on
//* all possible settings, making them excellent for general use. This library
//* can interface with sounds of either type.
//*
//* Known issues with sounds that this library resolves:
//* - A given sound variable can only be played once at a time. In order to
//* play a sound type multiple times at once, you need multiple variables.
//* - A sound cannot be played at the same instant that it is created.
//*
//* The DefineSound function defines a sound type based on some basic parameters
//* the user provides. DefineSoundEx is available if the user wants control over
//* all possible parameters, though they won't have an impact most of the time.
//* The duration parameter for DefineSound and DefineSoundEx is in milliseconds,
//* which is consistent with Blizzard's natives. To get the duration of a given
//* sound, open up the WE's Sound Editor, navigate to your sound, and select
//* "Add as Sound." In doing so, it will show its duration in seconds. Multiply
//* that number by 1000 and use it as the duration argument.
//*
//* This library returns a sound variable with RunSound that you can change the
//* settings of using the standard JASS sound API. The library assigns default
//* values to the parameters for 2-D and 3-D sounds, that way they will run
//* without any further help.
//*
//* The library automatically allocates, runs, and recycles a sound when you
//* call RunSound. This library will not automatically recycle looping sounds,
//* so you will need to call ReleaseSound on the looping sound when you want it
//* to end.
//*
//******************************************************************************
//*
//* > function DefineSound takes string fileName, integer duration, ...
//* boolean looping, boolean is3D returns integer
//*
//* This function defines a sound type with a short list of parameters. The
//* returned integer serves as a SOUND_TYPE for running this type of sound at
//* any other point in a map.
//*
//* > function DefineSoundEx takes string fileName, integer duration, ...
//* boolean looping, boolean is3D, boolean stopwhenoutofrange, ...
//* integer fadeInRate, integer fadeOutRate, string eaxSetting ...
//* returns integer
//*
//* This function serves an identical purpose to DefineSound, but gives the user
//* full control over the entire list of parameters. Similar to DefineSound, the
//* returned integer serves as a SOUND_TYPE for running this type of sound.
//*
//* > function RunSound takes integer soundRef returns sound
//*
//* This function runs a sound with the parameters held within the soundRef
//* integer argument. The soundRef argument is the returned value of DefineSound
//* or DefineSoundEx.
//*
//* > function RunSoundOnUnit takes integer soundRef, unit whichUnit returns sound
//*
//* The same as RunSound, just this function runs a sound of a given type on a
//* specified unit.
//*
//* > function RunSoundAtPoint takes integer soundRef, real x, real y, real z returns sound
//*
//* The same as RunSound, just this function runs a sound of a given type at a
//* specified point in 3D space.
//*
//* > function RunSoundForPlayer takes integer soundRef, player p returns sound
//*
//* The same as RunSound, just this function runs a sound of a given type only
//* for the specified player.
//*
//* > function ReleaseSound takes sound s returns boolean
//*
//* This function need only be called on looping sounds. If a sound is not
//* looping, it will be released and recycled on its own. This function should
//* be used on looping sounds when you want them to end.
//*
//* Example usage:
//* set SOUND_TYPE = DefineSound("Sound\\Path.wav", 300, false, true)
//* call RunSound(SOUND_TYPE)
//* call RunSoundOnUnit(SOUND_TYPE, SomeUnit)
//* call RunSoundAtPoint(SOUND_TYPE, x, y, z)
//* call RunSoundForPlayer(SOUND_TYPE, Player(5))
//* call ReleaseSound(SomeLoopingSound)
//*
globals
private hashtable ht = InitHashtable() //Attach sound types to sounds
private hashtable st = InitHashtable() //Sound hashtable
private hashtable rt = InitHashtable() //Attach soundrecyclers to sounds
private hashtable kt = InitHashtable() //Attach StopSound data
endglobals
//Struct for each sound type
private struct soundhelper
//Stack associated to each struct
Stack sta
//Sound Settings for this sound type
string fileName = ""
integer duration = 0
boolean looping = false
boolean is3D = false
boolean stopwhenoutofrange = false
integer fadeInRate = 0
integer fadeOutRate = 0
string eaxSetting = ""
static method create takes string fileName, integer duration, boolean looping, boolean is3D, boolean stopwhenoutofrange, integer fadeInRate, integer fadeOutRate, string eaxSetting returns soundhelper
local soundhelper sh = soundhelper.allocate()
//Load the parameters so the sound can be created later as necessary
set sh.fileName = fileName
set sh.duration = duration
set sh.looping = looping
set sh.is3D = is3D
set sh.stopwhenoutofrange = stopwhenoutofrange
set sh.fadeInRate = fadeInRate
set sh.fadeOutRate = fadeOutRate
set sh.eaxSetting = eaxSetting
//Create the stack for the struct
set sh.sta = Stack.create()
return sh
endmethod
endstruct
//Struct for holding data for the sound recycling
private struct soundrecycler
timer t = null
sound s = null
integer sh = 0
boolean stopped = false //Only gets used if StopSound is called on a new sound
static method create takes sound whichSound, integer soundRef returns soundrecycler
local soundrecycler sr = soundrecycler.allocate()
set sr.t = NewTimer()
set sr.s = whichSound
set sr.sh = soundRef
call SetTimerData(sr.t, integer(sr))
//Hook the value to the soundRef and whichSound
call SaveInteger(rt, soundRef, GetHandleId(whichSound), integer(sr))
return sr
endmethod
private method onDestroy takes nothing returns nothing
call RemoveSavedInteger(rt, .sh, GetHandleId(.s))
call ReleaseTimer(.t)
endmethod
endstruct
//******************************************************************************
private function HookStopSound takes sound soundHandle, boolean killWhenDone, boolean fadeOut returns nothing
local integer id = GetHandleId(soundHandle)
local integer soundRef = 0
local soundrecycler sr = 0
if HaveSavedInteger(ht, 0, id) then //Sound is from stacks
set soundRef = LoadInteger(ht, 0, id)
if HaveSavedInteger(rt, soundRef, id) then //Sound has a recycler
set sr = soundrecycler(LoadInteger(rt, soundRef, id))
set sr.stopped = true
endif
if killWhenDone then
debug call BJDebugMsg(SCOPE_PREFIX+"Warning: (StopSound) Destroying a sound in the stack")
endif
endif
endfunction
hook StopSound HookStopSound
private function HookKillSoundWhenDone takes sound soundHandle returns nothing
if HaveSavedInteger(ht, 0, GetHandleId(soundHandle)) then
call BJDebugMsg(SCOPE_PREFIX+"Warning: (KillSoundWhenDone) Destroying a sound in the stack")
endif
endfunction
debug hook KillSoundWhenDone HookKillSoundWhenDone
//******************************************************************************
function DefineSoundEx takes string fileName, integer duration, boolean looping, boolean is3D, boolean stopwhenoutofrange, integer fadeInRate, integer fadeOutRate, string eaxSetting returns integer
return integer(soundhelper.create(fileName, duration, looping, is3D, stopwhenoutofrange, fadeInRate, fadeOutRate, eaxSetting))
endfunction
function DefineSound takes string fileName, integer duration, boolean looping, boolean is3D returns integer
return DefineSoundEx(fileName, duration, looping, is3D, true, 10, 10, "CombatSoundsEAX")
endfunction
function ReleaseSound takes sound s returns boolean
local integer id = GetHandleId(s)
local integer soundRef = 0
local soundhelper sh = 0
local soundrecycler sr = 0
if s == null then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Cannot recycle a null sound")
return false
elseif not HaveSavedInteger(ht, 0, id) then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Cannot recycle a sound not allocated by RunSound")
return false
endif
set soundRef = LoadInteger(ht, 0, id)
set sh = soundhelper(soundRef)
call StopSound(s, false, true) //Stop the sound
call sh.sta.push(id) //Return it to the stack
call SaveSoundHandle(st, soundRef, id, s) //Save it to hashtable
if not sh.looping then
//soundrecycler only exists for non-looping sounds
set sr = soundrecycler(LoadInteger(rt, soundRef, id))
call sr.destroy() //Destroy recycler helper
endif
return true
endfunction
private function Recycle takes nothing returns nothing
local soundrecycler sr = soundrecycler(GetTimerData(GetExpiredTimer()))
local soundhelper sh = soundhelper(sr.sh)
local integer id = GetHandleId(sr.s)
call StopSound(sr.s, false, true) //Stop the sound
call sh.sta.push(id) //Return it to the stack
call SaveSoundHandle(st, integer(sh), id, sr.s) //Save it to hashtable
call sr.destroy() //Destroy recycler helper
endfunction
private function Run takes nothing returns nothing
local soundrecycler sr = soundrecycler(GetTimerData(GetExpiredTimer()))
local soundhelper sh = soundhelper(sr.sh)
if not sr.stopped then
call StartSound(sr.s) //Play sound here
endif
if not sh.looping and not sr.stopped then
call TimerStart(sr.t, sh.duration*0.001, false, function Recycle)
else
call sr.destroy()
endif
endfunction
function RunSound takes integer soundRef returns sound
local sound s = null
local integer i = 0
local soundhelper sh = soundhelper(soundRef)
local soundrecycler sr = 0
if soundRef <= 0 then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Cannot run sound of undefined type")
return null
endif
//Check if the stack is empty
if sh.sta.peek() == Stack.EMPTY then
//Create a new sound for the stack
set s = CreateSound(sh.fileName, sh.looping, sh.is3D, sh.stopwhenoutofrange, sh.fadeInRate, sh.fadeOutRate, sh.eaxSetting)
//Attach the type to the sound for future reference
call SaveInteger(ht, 0, GetHandleId(s), integer(sh))
call SetSoundDuration(s, sh.duration)
//Stuff that must be performed immediately upon creation of sounds
call SetSoundChannel(s, 5)
call SetSoundVolume(s, 127)
call SetSoundPitch(s, 1.)
if sh.is3D then
//These are settings necessary for 3-D sounds to function properly
//You can change them at will outside of this function
call SetSoundDistances(s, 600., 10000.)
call SetSoundDistanceCutoff(s, 3000.)
call SetSoundConeAngles(s, 0., 0., 127)
call SetSoundConeOrientation(s, 0., 0., 0.)
endif
//Start sound after a delay because it was created here
set sr = soundrecycler.create(s, soundRef)
call TimerStart(sr.t, 0.001, false, function Run)
else
//Allocate a sound from the stack
set i = sh.sta.pop()
if not HaveSavedHandle(st, soundRef, i) then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: No sound in given stack member")
return null
endif
set s = LoadSoundHandle(st, soundRef, i)
call RemoveSavedInteger(st, soundRef, i)
call SetSoundVolume(s, 127) //Start volume at max
//Start it here since it wasn't created here
call StartSound(s)
//Recycle the sound in a timer callback after it's finished if nonlooping
if not sh.looping then
set sr = soundrecycler.create(s, soundRef)
call TimerStart(sr.t, sh.duration*0.001, false, function Recycle)
endif
endif
return s
endfunction
function RunSoundOnUnit takes integer soundRef, unit whichUnit returns sound
local sound s = RunSound(soundRef)
call AttachSoundToUnit(s, whichUnit)
return s
endfunction
function RunSoundAtPoint takes integer soundRef, real x, real y, real z returns sound
local sound s = RunSound(soundRef)
call SetSoundPosition(s, x, y, z)
return s
endfunction
function RunSoundForPlayer takes integer soundRef, player p returns sound
local sound s = RunSound(soundRef)
if GetLocalPlayer() != p then
call SetSoundVolume(s, 0)
else
call SetSoundVolume(s, 127)
endif
return s
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Stack
//*****************************************************************
//* STACK
//*
//* written by: Anitarf
//*
//* This is an efficient implementation of a stack in vJass. Since
//* it is based on a linked list, I decided to add common list
//* methods to the data structure so it can function both as
//* a stack and a simple linked list.
//*
//* As a linked list, it has less functionality than Ammorth's
//* LinkedList, but is considerably faster. Note only that most of
//* the list methods have O(n) time complexity so they may not be
//* suitable for operations on very large lists, however due to
//* their simplicity the list would need to be really large for
//* this to become a problem.
//*
//* All stack methods are of course O(1) and as fast as possible.
//* If you just need a stack, this is definitely the best choice.
//*
//* set s=Stack.create() - Instanceates a new Stack object.
//* call s.destroy() - Destroys the Stack.
//*
//* Stack syntax:
//* call s.push(123) - Pushes the value 123 on the stack.
//* A stack may contain multiple
//* instances of the same value.
//* set i=s.peek() - Reads the top value of the stack
//* and stores it to the variable i.
//* set i=s.pop() - Removes the top value from the stack
//* and stores it to the variable i.
//* s.peek()==Stack.EMPTY - Checks if the stack is empty.
//*
//* List syntax:
//* call s.add(123) - Adds the value 123 to the list.
//* A list may contain multiple
//* instances of the same value.
//* s.size - The total number of values on the list.
//* s.contains(123) - Checks if the value 123 is on the list.
//* set n=s.count(123) - Stores the number of times the value
//* 123 is on the list to the variable n.
//* call s.remove(123) - Removes one instance of the value 123
//* from the list. Returns false if
//* the value was not found on the list.
//* call s.purge(123) - Removes all instances of the value 123
//* from the list. Returns the number of
//* values that were removed.
//* set i=s.first - Reads the first value from the list
//* and stores it to the variable i.
//* set i=s.random - Reads a random value from the list
//* and stores it to the variable i.
//* set s2=s.copy() - Makes a copy of the list and stores
//* it to the variable s2.
//* call s.enum(Func,b) - Calls function Func for all values
//* on the list. The function must follow
//* the Enum function interface.
//* b is a boolean value, if it is true
//* then the values will be enumerated
//* top to bottom, if false then bottom
//* to top.
//*****************************************************************
public function interface Enum takes integer value returns nothing
struct Stack
// Use a totally random number here, the more improbable someone uses it, the better.
// This is the value that is returned by .pop and .peek methods and .first and .random operators when called on an empty stack.
public static constant integer EMPTY=0x28829022
// End of calibration.
readonly integer size = 0
private integer top = 0
private static integer free = 1
private static integer array next
private static integer array value
method push takes integer i returns nothing
// Get an index from the list of free indexes.
local integer n=Stack.free
set Stack.free=Stack.next[n]
// Extend the list of free indexes if needed.
if Stack.free==0 then
set Stack.free=n+1
endif
// Store the value to the index.
set Stack.value[n]=i
// Add index to the top of the stack.
set Stack.next[n]=.top
set .top=n
set .size=.size+1
endmethod
method pop takes nothing returns integer
// Get the top index of stack.
local integer n=.top
// Safety check in case a user pops an empty stack.
if n==0 then
debug call BJDebugMsg("stack warning: .pop called on an empty stack!")
return Stack.EMPTY
endif
// Remove the top index from stack.
set .top=Stack.next[n]
set .size=.size-1
// Add the index to the list of free indexes.
set Stack.next[n]=Stack.free
set Stack.free=n
// Return the value.
return Stack.value[n]
endmethod
method peek takes nothing returns integer
// Read the value of the top index.
return Stack.value[.top]
endmethod
method add takes integer value returns nothing
call .push(value)
endmethod
method contains takes integer value returns boolean
// Get the first index of the list.
local integer i=.top
// Search through the list.
loop
// Stop the search when the end of the list is reached.
exitwhen i==0
// Stop the search if the value is found.
if Stack.value[i]==value then
return true
endif
// Get the next index of the list.
set i=Stack.next[i]
endloop
return false
endmethod
method count takes integer value returns integer
local integer count=0
// Get the first index of the list.
local integer i=.top
// Search through the list.
loop
// Stop the search when the end of the list is reached.
exitwhen i==0
// Increase the count if the value is found.
if Stack.value[i]==value then
set count=count+1
endif
// Get the next index of the list.
set i=Stack.next[i]
endloop
return count
endmethod
method operator first takes nothing returns integer
return .peek()
endmethod
method operator random takes nothing returns integer
local integer r=GetRandomInt(1,.size)
// Get the first index of the list.
local integer i=.top
// Loop through the list.
loop
// Stop the loop after a random amount of repeats.
set r=r-1
exitwhen r==0 or i==0
// Get the next index of the list.
set i=Stack.next[i]
endloop
return Stack.value[i]
endmethod
method remove takes integer value returns boolean
// Get the first index of the list.
local integer i1=.top
local integer i2
// Check if the first index holds the value.
if Stack.value[i1]==value then
call .pop()
return true
endif
// Search through the rest of the list.
loop
set i2=Stack.next[i1]
// Stop the search when the end of the list is reached.
exitwhen i2==0
// Check if the next index holds the value.
if Stack.value[i2]==value then
// Remove the index from the stack.
set Stack.next[i1]=Stack.next[i2]
// Add the removed index to the list of free indexes.
set Stack.next[i2]=Stack.free
set Stack.free=i2
set .size=.size-1
return true
endif
set i1=i2
endloop
return false
endmethod
method purge takes integer value returns integer
local integer count=0
local integer i1
local integer i2
// If the first index holds the value, pop it.
loop
// If the list is empty, return.
if .top==0 then
return count
endif
// Repeat until the first index doesn't hold the value.
exitwhen Stack.value[.top]!=value
call .pop()
set count=count+1
endloop
// Get the first index of the list.
set i1=.top
// Search through the rest of the list.
loop
set i2=Stack.next[i1]
// Stop the search when the end of the list is reached.
exitwhen i2==0
// Check if the next index holds the value.
if Stack.value[i2]==value then
// Remove the index from the stack.
set Stack.next[i1]=Stack.next[i2]
// Add the removed index to the list of free indexes.
set Stack.next[i2]=Stack.free
set Stack.free=i2
set .size=.size-1
set count=count+1
else
set i1=i2
endif
endloop
return count
endmethod
method enum takes Enum f, boolean top2bottom returns nothing
local integer array value
// Get the first index of the list.
local integer i1=.top
local integer i2=0
// Populate the array.
loop
exitwhen i1==0
set value[i2]=Stack.value[i1]
set i2=i2+1
set i1=Stack.next[i1]
endloop
// Call the Enum function for each value in the array.
set i1=i2-1
loop
exitwhen i2==0
set i2=i2-1
// Enumerate in which direction?
if top2bottom then
call f.evaluate(value[i1-i2])
else
call f.evaluate(value[i2])
endif
endloop
endmethod
method copy takes nothing returns Stack
local Stack that=Stack.create()
// Get the first index of the list.
local integer i1=.top
local integer i2
// Add a dummy index to the top of the new list.
call that.push(0)
set i2=that.top
loop
exitwhen i1==0
// Get an index from the list of free indexes and add it at the end of the list.
set Stack.next[i2]=Stack.free
set i2=Stack.next[i2]
set Stack.free=Stack.next[i2]
// Extend the list of free indexes if needed.
if Stack.free==0 then
set Stack.free=i2+1
endif
// Copy the value to the new index.
set Stack.value[i2]=Stack.value[i1]
set i1=Stack.next[i1]
endloop
// End the new list correctly.
set Stack.next[i2]=0
// Remove the dummy index.
call that.pop()
// Copy the size value to the new list.
set that.size=this.size
return that
endmethod
method onDestroy takes nothing returns nothing
local integer n
// Remove all remaining indexes from the stack.
loop
// Get the top index.
set n=.top
exitwhen n==0
// Remove it from the stack.
set .top=Stack.next[n]
// Add it to the list of free indexes.
set Stack.next[n]=Stack.free
set Stack.free=n
endloop
endmethod
static method onInit takes nothing returns nothing
// Store the EMPTY value to index 0 to make .peek inline friendly.
set Stack.value[0]=Stack.EMPTY
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//! zinc
/*
* PowerupSentinel
* ------------
* Placing this library in your map will automatically fix all rune/tome
* memory leaks in your map.
*
* Powerup items don't get removed automatically by the game, they instead
* just leave a small item in the map, this caused memory leaks but - worse -
* it also makes areas of your map where a lot of tomes have been used lag a lot.
*
*/
library PowerupSentinel
{
timer tic;
item queue[];
integer qn=0;
function onInit(){
trigger t = CreateTrigger();
tic = CreateTimer();
TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM);
TriggerAddCondition(t, function()->boolean {
queue[qn] = GetManipulatedItem();
qn = qn + 1;
TimerStart(tic, 0.0, false, function() {
integer i=0;
for( 0 <= i < qn ) {
if (GetWidgetLife(queue[i])<0.405) {
RemoveItem(queue[i]);
}
queue[i]=null;
}
qn = 0;
});
return false;
});
}
}
//! endzinc
//TESH.scrollpos=0
//TESH.alwaysfold=0
library AutoIndex
//===========================================================================
// Information:
//==============
//
// AutoIndex is a very simple script to utilize. Just call GetUnitId(unit)
// to get get the unique value assigned to a particular unit. The GetUnitId
// function is extremely fast because it inlines directly to a GetUnitUserData
// call. AutoIndex automatically assigns an ID to each unit as it enters the
// map, and instantly frees that ID as the unit leaves the map. Detection of
// leaving units is accomplished in constant time without a periodic scan.
//
// AutoIndex uses UnitUserData by default. If something else in your map
// would conflict with that, you can set the UseUnitUserData configuration
// constant to false, and a hashtable will be used instead. Note that hash-
// tables are about 60% slower.
//
// If you turn on debug mode, AutoIndex will be able to display several
// helpful error messages. The following issues will be detected:
// -Passing a removed or decayed unit to GetUnitId
// -Code outside of AutoIndex has overwritten a unit's UserData value.
// -GetUnitId was used on a filtered unit (a unit you don't want indexed).
//
// AutoIndex provides events upon indexing or deindexing units. This
// effectively allows you to notice when units enter or leave the game. Also
// included are the AutoData, AutoCreate, and AutoDestroy modules, which allow
// you to fully utilize AutoIndex's enter/leave detection capabilities in
// conjunction with your structs.
//
//===========================================================================
// How to install AutoIndex:
//===========================
//
// 1.) Copy and paste this script into your map.
// 2.) Save it to allow the ObjectMerger macro to generate the "Leave Detect"
// ability for you. Close and re-open the map. After that, disable the macro
// to prevent the delay while saving.
//
//===========================================================================
// How to use AutoIndex:
//=======================
//
// So you can get a unique integer for each unit, but how do you use that to
// attach data to a unit? GetUnitId will always return a number in the range of
// 1-8190. This means it can be used as an array index, as demonstrated below:
/*
globals
integer array IntegerData
real array RealData
SomeStruct array SomeStructData
englobals
function Example takes nothing returns nothing
local unit u = CreateUnit(Player(0), 'hpea', 0., 0., 0.)
local integer id = GetUnitId(u)
//You now have a unique index for the unit, so you can
//attach or retrieve data about the unit using arrays.
set IntegerData[id] = 5
set RealData[id] = 25.0
set SomeStructData[id] = SomeStruct.create()
//If you have access to the same unit in another function, you can
//retrieve the data by using GetUnitId() and reading the arrays.
endfunction
*/
// The UnitFilter function in the configuration section is provided so that
// you can make AutoIndex completely ignore certain unit-types. Ignored units
// won't be indexed or fire indexed/deindexed events. You may want to filter out
// dummy casters or system-private units, especially ones that use UnitUserData
// internally. xe dummy units are automatically filtered.
//
//===========================================================================
// How to use OnUnitIndexed / OnUnitDeindexed:
//=============================================
//
// AutoIndex will fire the OnUnitIndexed event when a unit enters the map,
// and the OnUnitDeindexed event when a unit leaves the map. Functions used
// as events must take a unit and return nothing. An example is given below:
/*
function UnitEntersMap takes unit u returns nothing
call BJDebugMsg(GetUnitName(u)+" with ID "+I2S(GetUnitId(u))+" entered the map.")
endfunction //Using GetUnitId() during Indexed events works fine...
function UnitLeavesMap takes unit u returns nothing
call BJDebugMsg(GetUnitName(u)+" with ID "+I2S(GetUnitId(u))+" left the map.")
endfunction //So does using GetUnitId() during Deindexed events.
function Init takes nothing returns nothing
call OnUnitIndexed(UnitEntersMap)
call OnUnitDeindexed(UnitLeavesMap)
endfunction
*/
// If you call OnUnitIndexed during map initialization, every existing
// unit will be considered as entering the map. This saves you from the need
// to manually enumerate preplaced units (or units created by initialization
// code that ran before OnUnitIndexed was called).
//
// OnUnitDeindexed runs while a unit still exists, which means you can
// still do things such as destroy special effects attached to the unit.
// The unit will cease to exist immediately after the event is over.
//
//===========================================================================
// AutoIndex API:
//================
//
// GetUnitId(unit) -> integer
// This function returns a unique ID in the range of 1-8190 for the
// specified unit. Returns 0 if a null unit was passed. This function
// inlines directly to GetUnitUserData or LoadInteger if debug mode
// is disabled. If debug mode is enabled, this function will print
// an error message when passed a decayed or filtered unit.
//
// IsUnitIndexed(unit) -> boolean
// This function returns a boolean indicating whether the specified
// unit has been indexed. The only time this will return false is
// for units you have filtered using the UnitFilter function, or
// for xe dummy units. You can use this function to easily detect
// dummy units and avoid performing certain actions on them.
//
// OnUnitIndexed(IndexFunc)
// This function accepts an IndexFunc, which must take a unit and
// return nothing. The IndexFunc will be fired instantly whenever
// a unit enters the map. You may use GetUnitId on the unit. When
// you call this function during map initialization, every existing
// unit will be considered as entering the map.
//
// OnUnitDeindexed(IndexFunc)
// Same as above, but runs whenever a unit is leaving the map. When
// this event runs, the unit still exists, but it will cease to exist
// as soon as the event ends. You may use GetUnitId on the unit.
//
//===========================================================================
// How to use AutoData:
//======================
//
// The AutoData module allows you to associate one or more instances
// of the implementing struct with units, as well as iterate through all
// of the instances associated with each unit.
//
// This association is accomplished through the "me" instance member,
// which the module will place in the implementing struct. Whichever unit
// you assign to "me" becomes the owner of that instance. You may change
// ownership by reassigning "me" to another unit at any time, or you may
// make the instance unowned by assigning "me" to null.
//
// AutoData implements the static method operator [] in your struct
// to allow you to access instances from their owning units. For example,
// you may type: local StructName s = StructName[u]. If u has been set
// to own an instance of StructName, s will be set to that instance.
//
// So, what happens if you assign the same owning unit to multiple
// instances? You may use 2D array syntax to access instances assigned to
// the same unit: local StructName s = StructName[u][n], where u is the
// owning unit, and n is the index beginning with 0 for each unit. You
// can access the size of a unit's instance list (i.e. the number of
// instances belonging to the unit) by using the .size instance member.
/*
struct Example
implement AutoData
static method create takes unit u returns Example
local Example this = allocate()
set me = u //Assigning the "me" member from AutoData.
return this
endmethod
endstruct
function Test takes nothing returns nothing
local unit u = CreateUnit(Player(0), 'hpea', 0., 0., 0.)
local Example e1 = Example.create(u)
local Example e2 = Example.create(u)
local Example e3 = Example.create(u)
local Example e
call BJDebugMsg(I2S(Example[u].size)) //Prints 3 because u owns e1, e2, and e3.
set e = Example[u][GetRandomInt(0, Example[u].size - 1)] //Random instance belonging to u.
set e = Example[u] //This is the fastest way to iterate the instances belonging
loop //to a specific unit, starting with the first instance.
exitwhen e == 0 //e will be assigned to 0 when no instances remain.
call BJDebugMsg(I2S(e)) //Prints the values of e1, e2, e3.
set e = e[e.index + 1] //"e.index" refers to the e's position in u's instance list.
endloop //Thus, index + 1 is next, and index - 1 is previous.
endfunction //This trick allows you to avoid a local counter.
*/
// AutoData restrictions:
// -You may not implement AutoData in any struct which has already
// declared static or non-static method operator [].
// -AutoData will conflict with anything named "me", "size", or
// "index" in the implementing struct.
// -AutoData may not be implemented in structs that extend array.
// -You may not declare your own destroy method. (This restriction
// can be dropped as soon as JassHelper supports module onDestroy).
//
// AutoData information:
// -You do not need to null the "me" member when destroying an
// instance. That is done for you automatically during destroy().
// (But if you use deallocate(), you must null "me" manually.)
// -StructName[u] and StructName[u][0] refer to the same instance,
// which is the first instance that was associated with unit u.
// -StructName[u][StructName[u].size - 1] refers to the instance that
// was most recently associated with unit u.
// -Instances keep their relative order in the list when one is removed.
//
//===========================================================================
// How to use AutoCreate:
//=======================
//
// The AutoCreate module allows you to automatically create instances
// of the implementing struct for units as they enter the game. AutoCreate
// automatically implements AutoData into your struct. Any time an instance
// is automatically created for a unit, that instance's "me" member will be
// assigned to the entering unit.
//
// AutoCreate restrictions:
// -All of the same restrictions as AutoData.
// -If your struct's allocate() method takes parameters (i.e. the parent
// type's create method takes parameters), you must declare a create
// method and pass those extra parameters to allocate yourself.
//
// AutoCreate information:
// -You may optionally declare the createFilter method, which specifies
// which units should recieve an instance as they enter the game. If
// you do not declare it, all entering units will recieve an instance.
// -You may optionally declare the onCreate method, which will run when
// AutoCreate automatically creates an instance. (This is just a stand-
// in until JassHelper supports the onCreate method.)
// -You may declare your own create method, but it must take a single
// unit parameter (the entering unit) if you do so.
/*
struct Example
private static method createFilter takes unit u returns boolean
return GetUnitTypeId(u) == 'hfoo' //Created only for Footmen.
endmethod
private method onCreate takes nothing returns nothing
call BJDebugMsg(GetUnitName(me)+" entered the game!")
endmethod
implement AutoCreate
endstruct
*/
//===========================================================================
// How to use AutoDestroy:
//=========================
//
// The AutoDestroy module allows you to automatically destroy instances
// of the implementing struct when their "me" unit leaves the game. AutoDestroy
// automatically implements AutoData into your struct. You must assign a unit
// to the "me" member of an instance for this module to have any effect.
//
// AutoDestroy restrictions:
// -All of the same restrictions as AutoData.
//
// AutoDestroy information:
// -If you also implement AutoCreate in the same struct, remember that it
// assigns the "me" unit automatically. That means you can have fully
// automatic creation and destruction.
/*
struct Example
static method create takes unit u returns Example
local Example this = allocate()
set me = u //You should assign a unit to "me",
return this //otherwise AutoDestroy does nothing.
endmethod //Not necessary if using AutoCreate.
private method onDestroy takes nothing returns nothing
call BJDebugMsg(GetUnitName(me)+" left the game!")
endmethod
implement AutoDestroy
endstruct
*/
//===========================================================================
// Configuration:
//================
// external ObjectMerger w3a Adef lvdt anam "Leave Detect" aart "" arac 0
//Save your map with this Object Merger call enabled, then close and reopen your
//map. Disable it by removing the exclamation to remove the delay while saving.
globals
private constant integer LeaveDetectAbilityID = 'lvdt'
//This rawcode must match the parameter after "Adef" in the
//ObjectMerger macro above. You may change both if you want.
private constant boolean UseUnitUserData = true
//If this is set to true, UnitUserData will be used. You should only set
//this to false if something else in your map already uses UnitUserData.
//A hashtable will be used instead, but it is about 60% slower.
private constant boolean SafeMode = true
//This is set to true by default so that GetUnitId() will ALWAYS work.
//If if this is set to false, GetUnitId() may fail to work in a very
//rare circumstance: creating a unit that has a default-on autocast
//ability, and using GetUnitId() on that unit as it enters the game,
//within a trigger that detects any order. Set this to false for a
//performance boost only if you think you can avoid this issue.
private constant boolean AutoDataFastMode = true
//If this is set to true, AutoData will utilize one hashtable per time
//it is implemented. If this is set to false, all AutoDatas will share
//a single hashtable, but iterating through the instances belonging to
//a unit will become about 12.5% slower. Your map will break if you
//use more than 255 hashtables simultaneously. Only set this to false
//if you suspect you will run out of hashtable instances.
endglobals
private function UnitFilter takes unit u returns boolean
return true
endfunction
//Make this function return false for any unit-types you want to ignore.
//Ignored units won't be indexed or fire OnUnitIndexed/OnUnitDeindexed
//events. The unit parameter "u" to refers to the unit being filtered.
//Do not filter out xe dummy units; they are automatically filtered.
//===========================================================================
// AutoData / AutoCreate / AutoDestroy modules:
//==============================================
function interface AutoCreator takes unit u returns nothing
function interface AutoDestroyer takes unit u returns nothing
globals
hashtable AutoData = null //If AutoDataFastMode is disabled, this hashtable will be
endglobals //initialized and shared between all AutoData implementations.
module AutoData
private static hashtable ht
private static thistype array data
private static integer array listsize
private static key typeid //Good thing keys exist to identify each implementing struct.
private unit meunit
private integer id
readonly integer index //The user can avoid using a local counter because this is accessable.
static method operator [] takes unit u returns thistype
return data[GetUnitId(u)]
endmethod //This is as fast as retrieving an instance from a unit gets.
method operator [] takes integer index returns thistype
static if AutoDataFastMode then //If fast mode is enabled...
return LoadInteger(ht, id, index)
else //Each instance has its own hashtable to associate unit and index.
return LoadInteger(AutoData, id, index*8190+typeid)
endif //Otherwise, simulate a 3D array associating unit, struct-type ID, and index.
endmethod //Somehow, this version is 12.5% slower just because of the math.
private method setIndex takes integer index, thistype data returns nothing
static if AutoDataFastMode then //Too bad you can't have a module-private operator []=.
call SaveInteger(ht, id, index, data)
else
call SaveInteger(AutoData, id, index*8190+typeid, data)
endif
endmethod
private method remove takes nothing returns nothing
if meunit == null then //If the struct doesn't have an owner...
return //Nothing needs to be done.
endif
loop
exitwhen index == listsize[id] //The last value gets overwritten by 0.
call setIndex(index, this[index + 1]) //Shift each element down by one.
set this[index].index = index //Update the shifted instance's index.
set index = index + 1
endloop
set listsize[id] = listsize[id] - 1
set data[id] = this[0] //Ensure thistype[u] returns the same value as thistype[u][0].
set meunit = null
endmethod
private method add takes unit u returns nothing
if meunit != null then //If the struct has an owner...
call remove() //remove it first.
endif
set meunit = u
set id = GetUnitId(u) //Cache GetUnitId for slight performance boost.
if data[id] == 0 then //If this is the first instance for this unit...
set data[id] = this //Update the value that thistype[u] returns.
endif
set index = listsize[id] //Remember the index for removal.
call setIndex(index, this) //Add to the array.
set listsize[id] = index + 1
endmethod
method operator me takes nothing returns unit
return meunit
endmethod
method operator me= takes unit u returns nothing
if u != null then //If assigning "me" a non-null value...
call add(u) //Add this instance to that unit's array.
else //If assigning "me" a null value...
call remove() //Remove this instance from that unit's array.
endif
endmethod
method operator size takes nothing returns integer
return listsize[id]
endmethod
method destroy takes nothing returns nothing
call deallocate()
call remove() //This makes removal automatic when an instance is destroyed.
endmethod
private static method onInit takes nothing returns nothing
static if AutoDataFastMode then //If fast mode is enabled...
set ht = InitHashtable() //Initialize one hashtable per instance.
else //If fast mode is disabled...
if AutoData == null then //If the hashtable hasn't been initialized yet...
set AutoData = InitHashtable() //Initialize the shared hashtable.
endif
endif
endmethod
endmodule
module AutoCreate
implement AutoData //AutoData is necessary for AutoCreate.
private static method creator takes unit u returns nothing
local thistype this
local boolean b = true //Assume that the instance will be created.
static if thistype.createFilter.exists then //If createFilter exists...
set b = createFilter(u) //evaluate it and update b.
endif
if b then //If the instance should be created...
static if thistype.create.exists then //If the create method exists...
set this = create(u) //Create the instance, passing the entering unit.
else //If the create method doesn't exist...
set this = allocate() //Just allocate the instance.
endif
set me = u //Assign the instance's owner as the entering unit.
static if thistype.onCreate.exists then //If onCreate exists...
call onCreate() //Call it, because JassHelper should do this anyway.
endif
endif
endmethod
private static method onInit takes nothing returns nothing
call AutoIndex.addAutoCreate(thistype.creator)
endmethod //During module initialization, pass the creator function to AutoIndex.
endmodule
module AutoDestroy
implement AutoData //AutoData is necessary for AutoDestroy.
static method destroyer takes unit u returns nothing
loop
exitwhen thistype[u] == 0
call thistype[u].destroy()
endloop
endmethod //Destroy each instance owned by the unit until none are left.
private static method onInit takes nothing returns nothing
call AutoIndex.addAutoDestroy(thistype.destroyer)
endmethod //During module initialization, pass the destroyer function to AutoIndex.
endmodule
//===========================================================================
// AutoIndex struct:
//===================
function interface IndexFunc takes unit u returns nothing
hook RemoveUnit AutoIndex.hook_RemoveUnit
hook ReplaceUnitBJ AutoIndex.hook_ReplaceUnitBJ
debug hook SetUnitUserData AutoIndex.hook_SetUnitUserData
private keyword getIndex
private keyword getIndexDebug
private keyword isUnitIndexed
private keyword onUnitIndexed
private keyword onUnitDeindexed
struct AutoIndex
private static trigger enter = CreateTrigger()
private static trigger order = CreateTrigger()
private static trigger creepdeath = CreateTrigger()
private static group preplaced = CreateGroup()
private static timer allowdecay = CreateTimer()
private static hashtable ht
private static boolean array dead
private static boolean array summoned
private static boolean array animated
private static boolean array nodecay
private static boolean array removing
private static IndexFunc array indexfuncs
private static integer indexfuncs_n = -1
private static IndexFunc array deindexfuncs
private static integer deindexfuncs_n = -1
private static IndexFunc indexfunc
private static AutoCreator array creators
private static integer creators_n = -1
private static AutoDestroyer array destroyers
private static integer destroyers_n = -1
private static unit array allowdecayunit
private static integer allowdecay_n = -1
private static boolean duringinit = true
private static boolean array altered
private static unit array idunit
//===========================================================================
static method getIndex takes unit u returns integer
static if UseUnitUserData then
return GetUnitUserData(u)
else
return LoadInteger(ht, 0, GetHandleId(u))
endif
endmethod //Resolves to an inlinable one-liner after the static if.
static method getIndexDebug takes unit u returns integer
if u == null then
return 0
elseif GetUnitTypeId(u) == 0 then
call BJDebugMsg("AutoIndex error: Removed or decayed unit passed to GetUnitId.")
elseif idunit[getIndex(u)] != u and GetIssuedOrderId() != 852056 then
call BJDebugMsg("AutoIndex error: "+GetUnitName(u)+" is a filtered unit.")
endif
return getIndex(u)
endmethod //If debug mode is enabled, use the getIndex method that shows errors.
private static method setIndex takes unit u, integer index returns nothing
static if UseUnitUserData then
call SetUnitUserData(u, index)
else
call SaveInteger(ht, 0, GetHandleId(u), index)
endif
endmethod //Resolves to an inlinable one-liner after the static if.
static method isUnitIndexed takes unit u returns boolean
return u != null and idunit[getIndex(u)] == u
endmethod
static method isUnitAnimateDead takes unit u returns boolean
return animated[getIndex(u)]
endmethod //Don't use this; use IsUnitAnimateDead from AutoEvents instead.
//===========================================================================
private static method onUnitIndexed_sub takes nothing returns nothing
call indexfunc.evaluate(GetEnumUnit())
endmethod
static method onUnitIndexed takes IndexFunc func returns nothing
set indexfuncs_n = indexfuncs_n + 1
set indexfuncs[indexfuncs_n] = func
if duringinit then //During initialization, evaluate the indexfunc for every preplaced unit.
set indexfunc = func
call ForGroup(preplaced, function AutoIndex.onUnitIndexed_sub)
endif
endmethod
static method onUnitDeindexed takes IndexFunc func returns nothing
set deindexfuncs_n = deindexfuncs_n + 1
set deindexfuncs[deindexfuncs_n] = func
endmethod
static method addAutoCreate takes AutoCreator func returns nothing
set creators_n = creators_n + 1
set creators[creators_n] = func
endmethod
static method addAutoDestroy takes AutoDestroyer func returns nothing
set destroyers_n = destroyers_n + 1
set destroyers[destroyers_n] = func
endmethod
//===========================================================================
private static method hook_RemoveUnit takes unit whichUnit returns nothing
set removing[getIndex(whichUnit)] = true
endmethod //Intercepts whenever RemoveUnit is called and sets a flag.
private static method hook_ReplaceUnitBJ takes unit whichUnit, integer newUnitId, integer unitStateMethod returns nothing
set removing[getIndex(whichUnit)] = true
endmethod //Intercepts whenever ReplaceUnitBJ is called and sets a flag.
private static method hook_SetUnitUserData takes unit whichUnit, integer data returns nothing
static if UseUnitUserData then
if idunit[getIndex(whichUnit)] == whichUnit then
if getIndex(whichUnit) == data then
call BJDebugMsg("AutoIndex error: Code outside AutoIndex attempted to alter "+GetUnitName(whichUnit)+"'s index.")
else
call BJDebugMsg("AutoIndex error: Code outside AutoIndex altered "+GetUnitName(whichUnit)+"'s index.")
if idunit[data] != null then
call BJDebugMsg("AutoIndex error: "+GetUnitName(whichUnit)+" and "+GetUnitName(idunit[data])+" now have the same index.")
endif
set altered[data] = true
endif
endif
endif //In debug mode, intercepts whenever SetUnitUserData is used on an indexed unit.
endmethod //Displays an error message if outside code tries to alter a unit's index.
//===========================================================================
private static method allowDecay takes nothing returns nothing
local integer n = allowdecay_n
loop
exitwhen n < 0
set nodecay[getIndex(allowdecayunit[n])] = false
set allowdecayunit[n] = null
set n = n - 1
endloop
set allowdecay_n = -1
endmethod //Iterate through all the units in the stack and allow them to decay again.
private static method detectStatus takes nothing returns boolean
local unit u = GetTriggerUnit()
local integer index = getIndex(u)
local integer n
if idunit[index] == u then //Ignore non-indexed units.
if not IsUnitType(u, UNIT_TYPE_DEAD) then
if dead[index] then //The unit was dead, but now it's alive.
set dead[index] = false //The unit has been resurrected.
//! runtextmacro optional RunAutoEvent("Resurrect")
//If AutoEvents is in the map, run the resurrection events.
if IsUnitType(u, UNIT_TYPE_SUMMONED) and not summoned[index] then
set summoned[index] = true //If the unit gained the summoned flag,
set animated[index] = true //it's been raised with Animate Dead.
//! runtextmacro optional RunAutoEvent("AnimateDead")
//If AutoEvents is in the map, run the Animate Dead events.
endif
endif
else
if not removing[index] and not dead[index] and not animated[index] then
set dead[index] = true //The unit was alive, but now it's dead.
set nodecay[index] = true //A dead unit can't decay for at least 0. seconds.
set allowdecay_n = allowdecay_n + 1 //Add the unit to a stack. After the timer
set allowdecayunit[allowdecay_n] = u //expires, allow the unit to decay again.
call TimerStart(allowdecay, 0., false, function AutoIndex.allowDecay)
//! runtextmacro optional RunAutoEvent("Death")
//If AutoEvents is in the map, run the Death events.
elseif removing[index] or (dead[index] and not nodecay[index]) or (not dead[index] and animated[index]) then
//If .nodecay was false and the unit is dead and was previously dead, the unit decayed.
//If .animated was true and the unit is dead, the unit died and exploded.
//If .removing was true, the unit is being removed or replaced.
set n = deindexfuncs_n
loop //Run the OnUnitDeindexed events.
exitwhen n < 0
call deindexfuncs[n].evaluate(u)
set n = n - 1
endloop
set n = destroyers_n
loop //Destroy AutoDestroy structs for the leaving unit.
exitwhen n < 0
call destroyers[n].evaluate(u)
set n = n - 1
endloop
call AutoIndex(index).destroy() //Free the index by destroying the AutoIndex struct.
set idunit[index] = null //Null this unit reference to prevent a leak.
endif
endif
endif
set u = null
return false
endmethod
//===========================================================================
private static method unitEntersMap takes unit u returns nothing
local integer index
local integer n = 0
if getIndex(u) != 0 then
return //Don't index a unit that already has an ID.
endif
static if LIBRARY_xebasic then
if GetUnitTypeId(u) == XE_DUMMY_UNITID then
return //Don't index xe dummy units.
endif
endif
if not UnitFilter(u) then
return //Don't index units that fail the unit filter.
endif
set index = create()
call setIndex(u, index) //Assign an index to the entering unit.
call UnitAddAbility(u, LeaveDetectAbilityID) //Add the leave detect ability to the entering unit.
call UnitMakeAbilityPermanent(u, true, LeaveDetectAbilityID) //Prevent it from disappearing on morph.
set dead[index] = IsUnitType(u, UNIT_TYPE_DEAD) //Reset all of the flags for the entering unit.
set summoned[index] = IsUnitType(u, UNIT_TYPE_SUMMONED) //Each of these flags are necessary to detect
set animated[index] = false //when a unit leaves the map.
set nodecay[index] = false
set removing[index] = false
debug set altered[index] = false //In debug mode, this flag tracks wheter a unit's index was altered.
set idunit[index] = u //Attach the unit that is supposed to have this index to the index.
if duringinit then //If a unit enters the map during initialization...
call GroupAddUnit(preplaced, u) //Add the unit to the preplaced units group. This ensures that
endif //all units are noticed by OnUnitIndexed during initialization.
loop //Create AutoCreate structs for the entering unit.
exitwhen n > creators_n
call creators[n].evaluate(u)
set n = n + 1
endloop
set n = 0
loop //Run the OnUnitIndexed events.
exitwhen n > indexfuncs_n
call indexfuncs[n].evaluate(u)
set n = n + 1
endloop
endmethod
private static method onIssuedOrder takes nothing returns boolean
static if SafeMode then //If SafeMode is enabled, perform this extra check.
if getIndex(GetTriggerUnit()) == 0 then //If the unit doesn't already have
call unitEntersMap(GetTriggerUnit()) //an index, then assign it one.
endif
endif
return GetIssuedOrderId() == 852056 //If the order is Undefend, allow detectStatus to run.
endmethod
private static method initEnteringUnit takes nothing returns boolean
call unitEntersMap(GetFilterUnit())
return false
endmethod
//===========================================================================
private static method afterInit takes nothing returns nothing
set duringinit = false //Initialization is over; set a flag.
call DestroyTimer(GetExpiredTimer()) //Destroy the timer.
call GroupClear(preplaced) //The preplaced units group is
call DestroyGroup(preplaced) //no longer needed, so clean it.
set preplaced = null
endmethod
private static method onInit takes nothing returns nothing
local region maparea = CreateRegion()
local rect bounds = GetWorldBounds()
local group g = CreateGroup()
local integer i = 15
static if not UseUnitUserData then
set ht = InitHashtable() //Only create a hashtable if it will be used.
endif
loop
exitwhen i < 0
call SetPlayerAbilityAvailable(Player(i), LeaveDetectAbilityID, false)
//Make the LeaveDetect ability unavailable so that it doesn't show up on the command card of every unit.
call TriggerRegisterPlayerUnitEvent(order, Player(i), EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
//Register the "EVENT_PLAYER_UNIT_ISSUED_ORDER" event for each player.
call GroupEnumUnitsOfPlayer(g, Player(i), function AutoIndex.initEnteringUnit)
//Enum every non-filtered unit on the map during initialization and assign it a unique
//index. By using GroupEnumUnitsOfPlayer, even units with Locust can be detected.
set i = i - 1
endloop
call TriggerAddCondition(order, And(function AutoIndex.onIssuedOrder, function AutoIndex.detectStatus))
//The detectStatus method will fire every time a non-filtered unit recieves an undefend order.
//And() is used here to avoid using a trigger action, which starts a new thread and is slower.
call TriggerRegisterPlayerUnitEvent(creepdeath, Player(12), EVENT_PLAYER_UNIT_DEATH, null)
call TriggerAddCondition(creepdeath, function AutoIndex.detectStatus)
//The detectStatus method must also fire when a neutral hostile creep dies, in case it was
//sleeping. Sleeping creeps don't fire undefend orders on non-damaging deaths.
call RegionAddRect(maparea, bounds) //GetWorldBounds() includes the shaded boundry areas.
call TriggerRegisterEnterRegion(enter, maparea, function AutoIndex.initEnteringUnit)
//The filter function of an EnterRegion trigger runs instantly when a unit is created.
call TimerStart(CreateTimer(), 0., false, function AutoIndex.afterInit)
//After any time elapses, perform after-initialization actions.
call GroupClear(g)
call DestroyGroup(g)
call RemoveRect(bounds)
set g = null
set bounds = null
endmethod
endstruct
//===========================================================================
// User functions:
//=================
function GetUnitId takes unit u returns integer
static if DEBUG_MODE then //If debug mode is enabled...
return AutoIndex.getIndexDebug(u) //call the debug version of GetUnitId.
else //If debug mode is disabled...
return AutoIndex.getIndex(u) //call the normal, inlinable version.
endif
endfunction
function IsUnitIndexed takes unit u returns boolean
return AutoIndex.isUnitIndexed(u)
endfunction
function OnUnitIndexed takes IndexFunc func returns nothing
call AutoIndex.onUnitIndexed(func)
endfunction
function OnUnitDeindexed takes IndexFunc func returns nothing
call AutoIndex.onUnitDeindexed(func)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library UnitListModule requires AutoIndex
//===========================================================================
// Information:
//==============
//
// This library provides the UnitList module, which allows you to easily
// create a linked list of struct instances associated with a particular unit.
// There is no faster method to associate a list of structs with a unit or to
// iterate through that list than the method this module uses. Whenever a unit
// leaves the game, all of the struct instances associated with that unit will
// be automatically destroyed. Aside from the fact that this module offers the
// best-possible peformance for this type of task, it is also able to greatly
// simplify the code of any system or spell that needs to associate multiple
// struct instances with a single unit.
//
//===========================================================================
// How to use the UnitList module:
//=================================
//
// Using the UnitList module is pretty simple. First, implement it in your
// struct (preferably at the top to avoid unnecessary TriggerEvaluate calls).
// In the struct's create method, you must call unitListAdd(u). The unit passed
// to this method will become the "owner" of that instance. (An instance may not
// be in more than one unit's list.) In the onDestroy method, you must also call
// unitListRemove(). An example is shown below:
//
/*
struct Example
implement UnitList
static method create takes unit u returns Example
local Example this = allocate()
call unitListAdd(u) //This instance has been added to this unit's list.
return this
endmethod
method onDestroy takes nothing returns nothing
call unitListRemove() //This instance has been removed from the unit's list.
endmethod
endstruct
*/
// The requirement to call unitListAdd() and unitListRemove() will be done
// away with once JassHelper supports module onDestroy and module onCreate, but
// for now, it is not too much of a burden.
//
// Once this is done, your struct will gain all of the methods detailed
// in the API section. Below is an example of how to iterate through the list
// of structs associated with a specific unit:
/*
function IterationExample takes unit u returns nothing
local Example e = Example.unitFirst(u)
loop
exitwhen e == 0
//Do something with e here.
call BJDebugMsg(GetUnitName(e.me))
//"me" refers to the unit that "owns" each struct instance.
set e = e.unitNext
endloop
//Use .unitLast(u) and .unitPrev instead to iterate backwards.
endmethod
*/
//
//===========================================================================
// UnitList module API:
//======================
//
// (static) unitCount(u) -> integer
// This method returns the number of structs of thistype associated with
// the specified unit.
//
// (static) unitFirst(u) -> thistype
// This method returns the first instance of thistype in the list of the
// specified unit.
//
// (static) unitLast(u) -> thistype
// This method returns the last instance of thistype in the list of the
// specified unit.
//
// unitNext -> thistype
// This member contains the next instance of thistype in the list of the
// "owner" this instance.
//
// unitPrev -> thistype
// This member contains the previous instance of thistype in the list of
// the "owner" this instance.
//
// unitListAdd(u)
// This method adds this instance to the list of structs of thistype for
// the specified unit. The unit passed to this method will become the
// "owner" of this struct instance. You may call it again to change the
// "owner".
//
// unitListRemove()
// This method removes this instance from the list of structs of thistype
// for the "owner" of this instance. This should usually be called in the
// onDestroy method of the implementing struct.
//
// (static) unitListDestroy(u)
// This method destroys all instances of thistype in the list of the spec-
// ified unit. This is called automatically on units as they leave the game.
//
// me -> unit
// This member contains the "owner" of this instance, as assigned by the
// unitListAdd(u) method. Contains null if no unit owns the instance.
//
//===========================================================================
module UnitList
private static boolean array destroying
private static integer array count
private static thistype array first
private static thistype array last
readonly thistype unitNext
readonly thistype unitPrev
readonly unit me
static method unitCount takes unit u returns integer
return count[GetUnitId(u)]
endmethod
static method unitFirst takes unit u returns thistype
return first[GetUnitId(u)]
endmethod
static method unitLast takes unit u returns thistype
return last[GetUnitId(u)]
endmethod
method unitListRemove takes nothing returns nothing
local integer id = GetUnitId(me)
if me == null then
return
endif
set me = null
if first[id] == this then
set first[id] = unitNext
endif
if last[id] == this then
set last[id] = unitPrev
endif
set unitPrev.unitNext = unitNext
set unitNext.unitPrev = unitPrev
set count[id] = count[id] - 1
endmethod
method unitListAdd takes unit u returns nothing
local integer id = GetUnitId(u)
if destroying[id] then
return
endif
if me != null then
call unitListRemove()
endif
set me = u
if first[id] == 0 then
set first[id] = this
else
set last[id].unitNext = this
set unitPrev = last[id]
endif
set last[id] = this
set count[id] = count[id] + 1
endmethod
static method unitListDestroy takes unit u returns nothing
local integer id = GetUnitId(u)
local thistype this = last[id]
set destroying[id] = true
loop
exitwhen this == 0
call destroy()
set this = unitPrev
endloop
set destroying[id] = false
endmethod
private static method onInit takes nothing returns nothing
call UnitListModule_AddUnitList(thistype.unitListDestroy)
endmethod
endmodule
//===========================================================================
function interface UnitListDestroyer takes unit u returns nothing
globals
public UnitListDestroyer array destroyers
public integer destroyers_n = -1
endglobals
public function AddUnitList takes UnitListDestroyer destroyer returns nothing
set destroyers_n = destroyers_n + 1
set destroyers[destroyers_n] = destroyer
endfunction
//! textmacro DestroyUnitLists
set n = UnitListModule_destroyers_n
loop
exitwhen n < 0
call UnitListModule_destroyers[n].evaluate(u)
set n = n - 1
endloop
//! endtextmacro
endlibrary
//TESH.scrollpos=101
//TESH.alwaysfold=0
library SpellEvent requires AutoIndex,UnitListModule
private function interface FunctionInterface takes nothing returns nothing
globals
private keyword s_spell
s_spell SpellEvent = 0
key SPELL_CHANNEL
key SPELL_CAST
key SPELL_EFFECT
key SPELL_FINISH // if the unit had succesfully finished the spell
key SPELL_ENDCAST // if the unit abort the spell before the end
endglobals
globals
private hashtable HashT
private timer Tim
private integer Index = 0
private FunctionInterface Func = 0
private s_spell array S
endglobals
private module m_init
static method onInit takes nothing returns nothing
local trigger trig
//! runtextmacro t_CreateSpellsTriggers("OnChannel","CHANNEL")
//! runtextmacro t_CreateSpellsTriggers("OnCast","CAST")
//! runtextmacro t_CreateSpellsTriggers("OnEffect","EFFECT")
//! runtextmacro t_CreateSpellsTriggers("OnFinish","FINISH")
//! runtextmacro t_CreateSpellsTriggers("OnEndCast","ENDCAST")
set Tim = CreateTimer()
set HashT = InitHashtable()
endmethod
endmodule
function RegisterSpellEvent takes integer whichEvent, integer whichSpell, FunctionInterface whichFunc returns nothing
call SaveInteger(HashT,whichEvent,whichSpell,integer(whichFunc))
endfunction
function RegisterSpellChannelResponse takes integer spellId, FunctionInterface whichFunc returns nothing
call SaveInteger(HashT,SPELL_CHANNEL,spellId,integer(whichFunc))
endfunction
function RegisterSpellCastResponse takes integer spellId, FunctionInterface whichFunc returns nothing
call SaveInteger(HashT,SPELL_CAST,spellId,integer(whichFunc))
endfunction
function RegisterSpellEffectResponse takes integer spellId, FunctionInterface whichFunc returns nothing
call SaveInteger(HashT,SPELL_EFFECT,spellId,integer(whichFunc))
endfunction
function RegisterSpellFinishResponse takes integer spellId, FunctionInterface whichFunc returns nothing
call SaveInteger(HashT,SPELL_FINISH,spellId,integer(whichFunc))
endfunction
function RegisterSpellEndCastResponse takes integer spellId, FunctionInterface whichFunc returns nothing
call SaveInteger(HashT,SPELL_ENDCAST,spellId,integer(whichFunc))
endfunction
private struct s_spell
integer AbilityId = 0
unit CastingUnit = null
unit TargetUnit = null
item TargetItem = null
destructable TargetDestructable = null
real TargetX = 0.
real TargetY = 0.
boolean IsTargetPoint = false
boolean IsTargetUnit = false
boolean IsTargetItem = false
boolean IsTargetDestructable = false
boolean IsNoTarget = false
integer TargetUnitTypeId = 0
integer TargetDestructableTypeId = 0
integer TargetItemTypeId = 0
boolean CastFinished = false
private method destroy takes nothing returns nothing
call .unitListRemove.evaluate()
set .CastFinished = false
endmethod
implement UnitList
private static method create takes nothing returns thistype
local thistype this = .allocate()
set .CastingUnit = GetSpellAbilityUnit()
set .TargetUnit = GetSpellTargetUnit()
set .AbilityId = GetSpellAbilityId()
if .TargetUnit != null then
set .IsTargetUnit = true
set .TargetUnitTypeId = GetUnitTypeId(.TargetUnit)
set .TargetX = GetUnitX(.TargetUnit)
set .TargetY = GetUnitY(.TargetUnit)
else
set .TargetDestructable = GetSpellTargetDestructable()
if .TargetDestructable != null then
set .IsTargetDestructable = true
set .TargetDestructableTypeId = GetDestructableTypeId(.TargetDestructable)
set .TargetX = GetDestructableX(.TargetDestructable)
set .TargetY = GetDestructableY(.TargetDestructable)
else
set .TargetItem = GetSpellTargetItem()
if .TargetItem != null then
set .IsTargetItem = true
set .TargetItemTypeId = GetItemTypeId(.TargetItem)
set .TargetX = GetItemX(.TargetItem)
set .TargetY = GetItemY(.TargetItem)
else
set .IsNoTarget = true
set .TargetX = GetSpellTargetX()
set .TargetY = GetSpellTargetY()
endif
endif
endif
call .unitListAdd(.CastingUnit)
return this
endmethod
private static method DestroyInstances takes nothing returns nothing
loop
exitwhen Index == 0
set Index = Index-1
call S[Index].destroy()
endloop
endmethod
private static method OnChannel takes nothing returns boolean
set SpellEvent = s_spell.create()
//! runtextmacro t_FindSpellFunctionInterface("CHANNEL")
return false
endmethod
private static method OnCast takes nothing returns boolean
//! runtextmacro t_FindWhichSpell()
//! runtextmacro t_FindSpellFunctionInterface("CAST")
return false
endmethod
private static method OnEffect takes nothing returns boolean
//! runtextmacro t_FindWhichSpell()
//! runtextmacro t_FindSpellFunctionInterface("EFFECT")
return false
endmethod
private static method OnFinish takes nothing returns boolean
//! runtextmacro t_FindWhichSpell()
set SpellEvent.CastFinished = true
//! runtextmacro t_FindSpellFunctionInterface("FINISH")
return false
endmethod
private static method OnEndCast takes nothing returns boolean
//! runtextmacro t_FindWhichSpell()
//! runtextmacro t_FindSpellFunctionInterface("ENDCAST")
set S[Index] = SpellEvent
set Index = Index+1
call TimerStart(Tim,0.,false,function thistype.DestroyInstances)
return false
endmethod
implement m_init
endstruct
//! textmacro t_FindWhichSpell
set SpellEvent = s_spell.unitFirst(GetSpellAbilityUnit())
loop
exitwhen SpellEvent.AbilityId == GetSpellAbilityId()
set SpellEvent = SpellEvent.unitNext
endloop
//! endtextmacro
//! textmacro t_CreateSpellsTriggers takes NAME , EVENT
set trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_SPELL_$EVENT$)
call TriggerAddCondition(trig,function s_spell.$NAME$)
//! endtextmacro
//! textmacro t_FindSpellFunctionInterface takes EVENT
set Func = FunctionInterface(LoadInteger(HashT,SPELL_$EVENT$,SpellEvent.AbilityId))
if Func != 0 then
call Func.execute()
endif
//! endtextmacro
endlibrary
//TESH.scrollpos=101
//TESH.alwaysfold=0
library OrbSys initializer init requires Table,BoundSentinel,TextDisplay,Resource
globals
private constant integer SLOT = 14
private constant string C = "The planet has to much buildings orbiting arround it."
private constant integer PIRATEBASE = 'o00I'
integer array CostUnitId [200]
integer array CostGold [200]
integer array CostLumber [200]
integer CostMax
endglobals
private keyword s_OrbSys
globals
private HandleTable TABLE
endglobals
private struct s_OrbSys
private unit planet
private unit array sat [SLOT]
private real array a [SLOT]
private real array d [SLOT]
private real angle = 0.00
method preventBuilding takes unit sat returns nothing
local integer i = 0
local player owner = GetOwningPlayer(sat)
call RemoveUnit(sat)
loop
set i = i + 1
exitwhen i > CostMax
if GetUnitTypeId(sat)== CostUnitId[i] then
call DisplayTextToPlayer(owner, 0, 0, C)
call ErrorSound(owner)
call SetResource(owner,CostGold[i],CostLumber[i])
set owner = null
return
endif
endloop
set owner = null
endmethod
method linkSat takes unit sat returns nothing
local integer i = 0
local real x = 0.
local real y = 0.
//Refresh: dead sat are cancelled
loop
exitwhen i > SLOT-1
if GetUnitState(.sat[i], UNIT_STATE_LIFE) <= 0 then
set .sat[i] = null
endif
set i = i + 1
endloop
//Seting the new satellite
set i = 0
loop
exitwhen i > SLOT-1
if .sat[i] == null and i <= 13 then
set .sat[i] = sat
call SetUnitPathing(sat,false)
set x = GetUnitX(.planet)+.d[i]*Cos(.a[i]*bj_DEGTORAD)
set y = GetUnitY(.planet)+.d[i]*Sin(.a[i]*bj_DEGTORAD)
call SetUnitPosition(sat,x,y)
return
endif
set i = i + 1
endloop
call .preventBuilding(sat)
endmethod
method setPlanetProperties takes nothing returns nothing
local integer i = 0
loop
exitwhen i > SLOT
if i <=5 then
set .a[i]= 60.00*i
set .d[i] = 100.
endif
if i >5 and i <= 13 then
set .a[i]= 45.00*i
set .d[i] = 162.5
endif
set i = i + 1
endloop
endmethod
method destroy takes nothing returns nothing
local integer i = 0
loop
exitwhen i > SLOT - 1
call KillUnit(.sat[i])
set .sat[i] = null
set i = i + 1
endloop
set .planet = null
endmethod
//Constructor
static method create takes unit planet returns s_OrbSys
local s_OrbSys this = s_OrbSys.allocate()
set this.planet = planet
return this
endmethod
endstruct
function OrbSys takes unit planet returns s_OrbSys
if( planet==null )then
return 0
endif
if( not TABLE.exists(planet) )then
set TABLE[planet] = s_OrbSys.create(planet)
endif
return s_OrbSys(TABLE[planet])
endfunction
private function AddPirateBase takes nothing returns boolean
if GetUnitTypeId(GetConstructedStructure()) == PIRATEBASE then
call OrbSys(GetConstructedStructure()).setPlanetProperties()
endif
return false
endfunction
private function AddPlanet takes nothing returns boolean
if IsUnitType(GetTriggerUnit(), UNIT_TYPE_ANCIENT) == true then
call OrbSys(GetTriggerUnit()).setPlanetProperties()
endif
return false
endfunction
private function DeathPlanet takes nothing returns boolean
if IsUnitType(GetTriggerUnit(), UNIT_TYPE_ANCIENT) == true then
call OrbSys(GetTriggerUnit()).destroy()
endif
return false
endfunction
private function AddSat takes nothing returns boolean
if IsUnitType(GetTrainedUnit(), UNIT_TYPE_MECHANICAL) == true and IsUnitType(GetTriggerUnit(), UNIT_TYPE_ANCIENT) == true then
call OrbSys(GetTriggerUnit()).linkSat(GetTrainedUnit())
endif
return false
endfunction
private function init takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
local trigger t3 = CreateTrigger()
local trigger t4 = CreateTrigger()
set TABLE = HandleTable.create()
call TriggerRegisterAnyUnitEventBJ(t1, EVENT_PLAYER_UNIT_TRAIN_FINISH )
call TriggerAddCondition(t1, Condition(function AddSat))
call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition(t2, Condition(function DeathPlanet))
call TriggerRegisterEnterRectSimple(t3, bj_mapInitialPlayableArea)
call TriggerAddCondition( t3, Condition( function AddPlanet ) )
call TriggerRegisterAnyUnitEventBJ(t4, EVENT_PLAYER_UNIT_CONSTRUCT_FINISH )
call TriggerAddCondition(t4, Condition(function AddPirateBase))
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope PlanetChangeOwner initializer init
private function Conditions takes nothing returns boolean
local unit planet = GetTriggerUnit()
local player owner = GetOwningPlayer(planet)
if IsUnitType(planet, UNIT_TYPE_ANCIENT) == true then
//Dock MkII +1
if CountUnitsOfType(owner,'h00S')<= 6 then
call SetPlayerTechMaxAllowed(owner, 'h00S', GetPlayerTechMaxAllowed(owner,'h00S')+1)
endif
//Dock MkIII +1
if CountUnitsOfType(owner,'h00T')<= 6 then
call SetPlayerTechMaxAllowed(owner, 'h00T', GetPlayerTechMaxAllowed(owner,'h00T')+1)
endif
//Total docks <=12 => dock MkI + 1
if CountUnitsOfType(owner,'h004') + CountUnitsOfType(owner,'h00S') +CountUnitsOfType(owner,'h00T')<= 12 then
call SetPlayerTechMaxAllowed(owner, 'h004', GetPlayerTechMaxAllowed(owner,'h004')+1)
endif
//Warehouse +1
call SetPlayerTechMaxAllowed(owner, 'h00F', GetPlayerTechMaxAllowed(owner,'h00F')+1)
//Total Research Facilities hors Research Facilities base <=8 => Research Faiclity Base +1
if CountUnitsOfType(owner,'h01A')+CountUnitsOfType(owner,'h01B')+CountUnitsOfType(owner,'h014')+CountUnitsOfType(owner,'h019')<= 8 then
call SetPlayerTechMaxAllowed(owner, 'h003', GetPlayerTechMaxAllowed(owner,'h003')+1)
endif
//Weapon Center + 1
call SetPlayerTechMaxAllowed(owner, 'h019', GetPlayerTechMaxAllowed(owner,'h019')+1)
//Structure Center +1
call SetPlayerTechMaxAllowed(owner, 'h014', GetPlayerTechMaxAllowed(owner,'h014')+1)
//Energery Center +1
call SetPlayerTechMaxAllowed(owner, 'h01A', GetPlayerTechMaxAllowed(owner,'h01A')+1)
//Production Center +1
call SetPlayerTechMaxAllowed(owner, 'h01B', GetPlayerTechMaxAllowed(owner,'h01B')+1)
//Total shipyards <=6 => Shipyard mkI +1
if CountUnitsOfType(owner,'h002') + CountUnitsOfType(owner,'h011') +CountUnitsOfType(owner,'h012')<= 6 then
call SetPlayerTechMaxAllowed(owner, 'h002', GetPlayerTechMaxAllowed(owner,'h002')+1)
endif
//Shipyard Mark II +1
call SetPlayerTechMaxAllowed(owner, 'h011', GetPlayerTechMaxAllowed(owner,'h011')+1)
//Shipyard Mark III +1
call SetPlayerTechMaxAllowed(owner, 'h012', GetPlayerTechMaxAllowed(owner,'h012')+1)
//AA Turret
call SetPlayerTechMaxAllowed(owner, 'h006', GetPlayerTechMaxAllowed(owner,'h006')+2)
//Ion Canon
call SetPlayerTechMaxAllowed(owner, 'h007', GetPlayerTechMaxAllowed(owner,'h007')+3)
//Torpedo Launchers +1
if CountUnitsOfType(owner,'h005')<= 6 then
call SetPlayerTechMaxAllowed(owner, 'h005', GetPlayerTechMaxAllowed(owner,'h005')+1)
endif
//Radar Tower+1
if Merchant[GetPlayerId(owner)]==true and GetPlayerTechMaxAllowed(owner,'h016')<= 6 then
call SetPlayerTechMaxAllowed(owner, 'h016', GetPlayerTechMaxAllowed(owner,'h016')+1)
endif
//MicroMissile Thrower+1
if Military[GetPlayerId(owner)]==true and GetPlayerTechMaxAllowed(owner,'h018')<=6 then
call SetPlayerTechMaxAllowed(owner, 'h018', GetPlayerTechMaxAllowed(owner,'h018')+6)
endif
//Total tourelles hors Turret base <=20 => TurretBase+1
if CountUnitsOfType(owner,'h007')+ CountUnitsOfType(owner,'h018')+ CountUnitsOfType(owner,'h006')+ CountUnitsOfType(owner,'h005')<=20 then
call SetPlayerTechMaxAllowed(owner, 'h010', GetPlayerTechMaxAllowed(owner,'h010')+1)
endif
//Training Center+1
call SetPlayerTechMaxAllowed(owner, 'h00Z', GetPlayerTechMaxAllowed(owner,'h00Z')+1)
//Si Stations <5 => Station + 1
if CountUnitsOfType(owner,'h001')<= 5 then
call SetPlayerTechMaxAllowed(owner, 'h001', GetPlayerTechMaxAllowed(owner,'h001')+1)
endif
endif
set owner = null
set planet = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_CHANGE_OWNER )
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope PirateBaseCreated initializer init
private function Conditions takes nothing returns boolean
local unit base = GetConstructedStructure()
local player owner = GetOwningPlayer(base)
if GetUnitTypeId(base) == 'o00I' then
//Dock MkII +1
if CountUnitsOfType(owner,'h00S')<= 6 then
call SetPlayerTechMaxAllowed(owner, 'h00S', GetPlayerTechMaxAllowed(owner,'h00S')+1)
endif
//Dock MkIII +1
if CountUnitsOfType(owner,'h00T')<= 6 then
call SetPlayerTechMaxAllowed(owner, 'h00T', GetPlayerTechMaxAllowed(owner,'h00T')+1)
endif
//Total docks <=12 => dock MkI + 1
if CountUnitsOfType(owner,'h004') + CountUnitsOfType(owner,'h00S') +CountUnitsOfType(owner,'h00T')<= 12 then
call SetPlayerTechMaxAllowed(owner, 'h004', GetPlayerTechMaxAllowed(owner,'h004')+1)
endif
//Warehouse +1
call SetPlayerTechMaxAllowed(owner, 'h00F', GetPlayerTechMaxAllowed(owner,'h00F')+1)
//Total Research Facilities hors Research Facilities base <=8 => Research Faiclity Base +1
if CountUnitsOfType(owner,'h01A')+CountUnitsOfType(owner,'h01B')+CountUnitsOfType(owner,'h014')+CountUnitsOfType(owner,'h019')<= 8 then
call SetPlayerTechMaxAllowed(owner, 'h003', GetPlayerTechMaxAllowed(owner,'h003')+1)
endif
//Weapon Center + 1
call SetPlayerTechMaxAllowed(owner, 'h019', GetPlayerTechMaxAllowed(owner,'h019')+1)
//Structure Center +1
call SetPlayerTechMaxAllowed(owner, 'h014', GetPlayerTechMaxAllowed(owner,'h014')+1)
//Energery Center +1
call SetPlayerTechMaxAllowed(owner, 'h01A', GetPlayerTechMaxAllowed(owner,'h01A')+1)
//Production Center +1
call SetPlayerTechMaxAllowed(owner, 'h01B', GetPlayerTechMaxAllowed(owner,'h01B')+1)
//Total shipyards <=6 => Shipyard mkI +1
if CountUnitsOfType(owner,'h002') + CountUnitsOfType(owner,'h011') +CountUnitsOfType(owner,'h012')<= 6 then
call SetPlayerTechMaxAllowed(owner, 'h002', GetPlayerTechMaxAllowed(owner,'h002')+1)
endif
//Shipyard Mark II +1
call SetPlayerTechMaxAllowed(owner, 'h011', GetPlayerTechMaxAllowed(owner,'h011')+1)
//Shipyard Mark III +1
call SetPlayerTechMaxAllowed(owner, 'h012', GetPlayerTechMaxAllowed(owner,'h012')+1)
//AA Turret
call SetPlayerTechMaxAllowed(owner, 'h006', GetPlayerTechMaxAllowed(owner,'h006')+2)
//Ion Canon
call SetPlayerTechMaxAllowed(owner, 'h007', GetPlayerTechMaxAllowed(owner,'h007')+3)
//Torpedo Launchers +1
if CountUnitsOfType(owner,'h005')<= 6 then
call SetPlayerTechMaxAllowed(owner, 'h005', GetPlayerTechMaxAllowed(owner,'h005')+1)
endif
//Radar Tower+1
if Merchant[GetPlayerId(owner)]==true and GetPlayerTechMaxAllowed(owner,'h016')<= 6 then
call SetPlayerTechMaxAllowed(owner, 'h016', GetPlayerTechMaxAllowed(owner,'h016')+1)
endif
//MicroMissile Thrower+1
if Military[GetPlayerId(owner)]==true and GetPlayerTechMaxAllowed(owner,'h018')<=6 then
call SetPlayerTechMaxAllowed(owner, 'h018', GetPlayerTechMaxAllowed(owner,'h018')+6)
endif
//Total tourelles hors Turret base <=20 => TurretBase+1
if CountUnitsOfType(owner,'h007')+ CountUnitsOfType(owner,'h018')+ CountUnitsOfType(owner,'h006')+ CountUnitsOfType(owner,'h005')<=20 then
call SetPlayerTechMaxAllowed(owner, 'h010', GetPlayerTechMaxAllowed(owner,'h010')+1)
endif
//Training Center+1
call SetPlayerTechMaxAllowed(owner, 'h00Z', GetPlayerTechMaxAllowed(owner,'h00Z')+1)
//Si Stations <5 => Station + 1
if CountUnitsOfType(owner,'h001')<= 5 then
call SetPlayerTechMaxAllowed(owner, 'h001', GetPlayerTechMaxAllowed(owner,'h001')+1)
endif
endif
set owner = null
set base = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_CONSTRUCT_FINISH )
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope meteorites initializer init
globals
private constant integer METEORID = 'n003'
private real XMin
private real YMin
private real XMax
private real YMax
endglobals
private function SpawnMeteors takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = 0
local integer j = 0
local real x = 0.
local real y = 0.
loop
exitwhen i > MAXPLAYER
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
set j = 0
loop
exitwhen j > 3
set x = GetRandomReal(XMin,XMax)
set y = GetRandomReal(YMin,YMax)
call UnitApplyTimedLife(CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE),METEORID,x,y,0.),'BTLF',60.)
set j = j + 1
endloop
endif
set i = i + 1
endloop
endfunction
private function Conditions takes nothing returns boolean
local timer t = NewTimer()
set XMin = GetRectMinX(bj_mapInitialPlayableArea)
set YMin = GetRectMinY(bj_mapInitialPlayableArea)
set XMax = GetRectMaxX(bj_mapInitialPlayableArea)
set YMax = GetRectMaxY(bj_mapInitialPlayableArea)
call TimerStart (t, 60., true, function SpawnMeteors )
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterTimerEventSingle( t, 15. )
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope ecneb initializer init
globals
private constant string FX = "MonsoonBoltTarget.mdx"
endglobals
private function Conditions takes nothing returns boolean
if GetAttacker()==DummyAttackerNebula then
call DestroyEffect(AddSpecialEffectTarget(FX,GetTriggerUnit(),"origin"))
endif
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
library AllianceSystem initializer init needs TextDisplay,SoundUtils,JSDialog,Table
globals
private constant string ALLY_COMMAND = "-ally"
private constant string UNALLY_COMMAND = "-unally"
//string array AllianceAlt1 [12]
//string array AllianceAlt2 [12]
//string array AllianceAlt3 [12]
integer array PlayerAllies [12]
private StringTable Str_table
private integer AllyCommand_length
private integer UnAllyCommand_length
endglobals
//! textmacro t__AllianceSystem_Init takes PLAYER_NUMBER , COMMAND
// j'ai fait la textmacro en partant de l'hypothèse que pour la commande l'index minimum est 1 et non 0, comme les joueurs en gui
set Str_table[I2S($PLAYER_NUMBER$)] = $PLAYER_NUMBER$
set Str_table["$COMMAND$"] = $PLAYER_NUMBER$
set Str_table[(GetPlayerName(Player($PLAYER_NUMBER$-1)))] = $PLAYER_NUMBER$ // si un joueur peut changer de nom en cours de partie, il faut effacer cette valeur et remplacer avec le nouveau nom du joueur
//! endtextmacro
private function SetAlliancesVariables takes nothing returns nothing
//! runtextmacro t__AllianceSystem_Init(" 1","red")
//! runtextmacro t__AllianceSystem_Init(" 2","blue")
//! runtextmacro t__AllianceSystem_Init(" 3","teal")
//! runtextmacro t__AllianceSystem_Init(" 4","purple")
//! runtextmacro t__AllianceSystem_Init(" 5","yellow")
//! runtextmacro t__AllianceSystem_Init(" 6","orange")
//! runtextmacro t__AllianceSystem_Init(" 7","green")
//! runtextmacro t__AllianceSystem_Init(" 8","pink")
//! runtextmacro t__AllianceSystem_Init(" 9","grey")
//! runtextmacro t__AllianceSystem_Init(" 10","light blue")
//! runtextmacro t__AllianceSystem_Init(" 11","dark green")
//! runtextmacro t__AllianceSystem_Init(" 12","brown")
endfunction
private function SetAccept takes integer key , unit whichUnit, integer dialogInteger, string btnString, integer id returns nothing
call DisplayTextToPlayer(Player(key),0.,0.,"You are now allied with "+PlayerColor[id]+GetPlayerName(Player(id)))
call DisplayTextToPlayer(Player(id),0.,0.,"You are now allied with "+PlayerColor[key]+GetPlayerName(Player(key)))
call RunSoundForPlayer(SOUND_HINT,Player(key))
call RunSoundForPlayer(SOUND_HINT,Player(id))
call SetPlayerAllianceStateBJ(Player(key),Player(id),bj_ALLIANCE_ALLIED_VISION)
call SetPlayerAllianceStateBJ(Player(id),Player(key),bj_ALLIANCE_ALLIED_VISION)
set PlayerAllies[key]=PlayerAllies[key]+1
set PlayerAllies[id]=PlayerAllies[id]+1
endfunction
private function SetRefuse takes integer key , unit whichUnit, integer dialogInteger, string btnString, integer id returns nothing
call RunSoundForPlayer(SOUND_ERROR,Player(key))
call RunSoundForPlayer(SOUND_ERROR,Player(id))
call DisplayTextToPlayer(Player(key),0.,0.,"You have refused to be allied with "+PlayerColor[id]+GetPlayerName(Player(id)))
call DisplayTextToPlayer(Player(id),0.,0.,PlayerColor[key]+GetPlayerName(Player(key))+" has refused the alliance")
endfunction
private function IsPlayerIndexInvalid takes integer i returns boolean
return Terrorist[i] or Alien[i]
endfunction
private function SetAlliance takes nothing returns boolean
local player whichPlayer = GetTriggerPlayer()
local integer whichPlayerId = GetPlayerId(whichPlayer)
local string text = GetEventPlayerChatString()
local integer string_length = StringLength(text)
local integer index
if IsPlayerIndexInvalid(whichPlayerId) then
call ErrorSound(whichPlayer)
call DisplayTextToPlayer(whichPlayer,0.,0.,"As Terrorist or Alien you can not ally anyone")
return false //works only when player is not alien/terrorist
endif
if SubString(text,0,AllyCommand_length) == ALLY_COMMAND then
set text = SubString(text,AllyCommand_length+1,string_length) // on extrait la commande après le "-ally" ou ce que tu as spécifié comme string pour l'alliance (ALLY_COMMAND)
set index = Str_table[text] // récupération de l'index du joueur concerné
if index == 0 then // commande invalide
call ErrorSound(whichPlayer)
call DisplayTextToPlayer(whichPlayer,0.,0.,"Invalide Player ID")
set whichPlayer = null
return false
endif
set index = index-1 // GUI style
if IsPlayerIndexInvalid(index) then
call ErrorSound(whichPlayer)
call DisplayTextToPlayer(whichPlayer,0.,0.,PlayerColor[index]+GetPlayerName(Player(index))+"|r can not have allies.")
set whichPlayer = null
return false
endif
if not IsPlayerAlly(whichPlayer,Player(index)) then //if players not already allied
if PlayerAllies[whichPlayerId]<3 then //if less than 3 allies, i don't care everybody <3 me
call Clear(index,PlayerColor[whichPlayerId]+GetPlayerName(whichPlayer)+"|r wants to ally you", null,0 )
call AddButton(index,"Accept", SetAccept, index, null, whichPlayerId)
call AddButton(index,"Refuse", SetRefuse, index, null, whichPlayerId)
call Show(index)
else
call ErrorSound(whichPlayer)
call DisplayTextToPlayer(whichPlayer,0.,0.,"You have already 3 allies.")
set whichPlayer = null
return false
endif
else //if players are already allied
call ErrorSound(whichPlayer)
call DisplayTextToPlayer(whichPlayer,0.,0.,"You already are allied to "+PlayerColor[index]+GetPlayerName(Player(index)))
set whichPlayer = null
return false
endif
elseif SubString(text,0,UnAllyCommand_length) == UNALLY_COMMAND then
set text = SubString(text,UnAllyCommand_length+1,string_length) // on extrait la commande après le "-ally" ou ce que tu as spécifié comme string pour l'alliance (ALLY_COMMAND)
set index = Str_table[text] // récupération de l'index du joueur concerné
if index == 0 then // commande invalide
call ErrorSound(whichPlayer)
call DisplayTextToPlayer(whichPlayer,0.,0.,"Invalide Player ID")
set whichPlayer = null
return false
endif
set index = index-1 // GUI style
if IsPlayerEnemy(whichPlayer,Player(index))==false then
call SetPlayerAllianceStateBJ(whichPlayer,Player(index),bj_ALLIANCE_UNALLIED)
call SetPlayerAllianceStateBJ(Player(index),whichPlayer,bj_ALLIANCE_UNALLIED)
call DisplayTextToPlayer(Player(index),0.,0.,PlayerColor[whichPlayerId]+GetPlayerName(whichPlayer)+"|r has declared war to you")
call DisplayTextToPlayer(whichPlayer,0.,0.,"You have declared the war to: "+PlayerColor[index]+GetPlayerName(Player(index)))
call RunSoundForPlayer(SOUND_ALARM,Player(index))
call RunSoundForPlayer(SOUND_ALARM,whichPlayer)
set PlayerAllies[whichPlayerId]=PlayerAllies[whichPlayerId]-1
set PlayerAllies[index]=PlayerAllies[index]-1
set whichPlayer = null
return false
else
call ErrorSound(whichPlayer)
call DisplayTextToPlayer(whichPlayer,0.,0.,"You already are in war with "+PlayerColor[index]+GetPlayerName(Player(index)))
set whichPlayer = null
return false
endif
endif
return false
// c'est vraiment trop la misère avec tes if j'ai passé plus d'1 heure pour en arriver jusque là !!!!!!
// j'ai arrêté les frais, mais je suppose que c'est suffisant
// NE LES IMBRIQUE PAS TANT QUE CELA OMG LAISSE LES RESPIRER ...
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
set Str_table = StringTable.create()
set AllyCommand_length = StringLength(ALLY_COMMAND)
set UnAllyCommand_length = StringLength(UNALLY_COMMAND)
call SetAlliancesVariables()
loop
exitwhen i > MAXPLAYER
set PlayerAllies[i]=0
call TriggerRegisterPlayerChatEvent( t, Player(i), ALLY_COMMAND, false )
call TriggerRegisterPlayerChatEvent( t, Player(i), UNALLY_COMMAND, false )
set i = i + 1
endloop
call TriggerAddCondition(t, Condition(function SetAlliance))
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope hcam initializer init
globals
private constant string COM = "-cam"
endglobals
private function Conditions takes nothing returns boolean
local player whichPlayer = GetTriggerPlayer()
local real height = S2R(SubString(GetEventPlayerChatString(), 5, 9))
if height > 50 and height < 4001 then
if whichPlayer == GetLocalPlayer() then
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, height, 1.00)
endif
else
call ErrorSound(whichPlayer)
call DisplayTextToPlayer(whichPlayer,0.,0.,"Camera argument must be between 50 and 4000")
endif
set whichPlayer = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
exitwhen i > MAXPLAYER
call TriggerRegisterPlayerChatEvent( t, Player(i), COM, false )
set i = i + 1
endloop
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope pclear initializer init
globals
private constant string COM1 = "-clear"
private constant string COM2 = "-Clear"
endglobals
private function Conditions takes nothing returns boolean
local integer i = 0
local player whichPlayer = GetTriggerPlayer()
loop
exitwhen i > 20
call DisplayTextToPlayer(whichPlayer,0.,0.," ")
set i = i + 1
endloop
set whichPlayer = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
exitwhen i > MAXPLAYER
call TriggerRegisterPlayerChatEvent( t, Player(i), COM1, true )
call TriggerRegisterPlayerChatEvent( t, Player(i), COM2, true )
set i = i + 1
endloop
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
library HelpCenter initializer init
globals
private constant real DUR = 30. //the text will be displayed during DUR seconds
private constant string COM = "-help" //string entered to run the trigger
private constant string LINE = "|c00AFAAFF"+"=============================================================="+"|r"//To separate text
private constant string NAME = "|c00AFAAFF"+"Help Center"+"|r" //Title displayed each time the trigger starts
private constant string INFO = "Enter -help XXXX where XXXX is one of the following key words:" //Text displayed then
string array HelpName [30] //The real title of each keyword, there, 30 keywords maximum
string array HelpText [30][15] //The content of each keywords: up to 15 sentences wroten
constant integer HelpTextMax = 15//Maximum amount of sentence displayed
integer HelpMax = 0
private StringTable Str_table
private integer HelpCommand_length
endglobals
//! textmacro t__HelpSystem_Init takes TEXT_ID, TITLE1 ,TITLE2
set Str_table["$TEXT_ID$"] = $TEXT_ID$
set Str_table["$TITLE1$"] = $TEXT_ID$
set Str_table["$TITLE2$"] = $TEXT_ID$
//! endtextmacro
private function SetTextVariables takes nothing returns nothing
local integer i = 1
//Respect the order of letters is better.
set HelpName[i]= "Alien"
set HelpText[i][0]="Can not colonize planet or build structures."
set HelpText[i][1]="Can not collect resources."
set HelpText[i][2]="Do not have income."
set HelpText[i][3]="Can only build light shuttle."
set HelpText[i][4]="Can improve units by making them assemblate."
set HelpText[i][5]="Really different units than other ways."
set HelpText[i][6]= "Aliens earn XP by assimilating planets."
//! runtextmacro t__HelpSystem_Init("i","alien","aliens")
set i = i + 1
//
set HelpName[i]= "Assimilate"
set HelpText[i][0]= "Assimilate is available for Aliens only."
set HelpText[i][1]= "To assimilate a planet, which will grants you Resources (Iron and Pulsars), you need to send an Alien Mothership or Omega Cruiser to the planet target."
set HelpText[i][2]= "Then you have to use the skill of the Mothership or the Omega Cruiser called Assimilate by targeting the planet with this skill."
set HelpText[i][3]= "This skill works on all planets."
set HelpText[i][4]= "If Assimilate is a success, you will get more Resources and you will be receive more Alpha Light Shuttles."
set HelpText[i][5]= "Assimilation grants XP"
//! runtextmacro t__HelpSystem_Init("i","assimilate","assimilise")
set i = i + 1
//
set HelpName[i]= "Asteroid"
set HelpText[i][0]= "Asteroids are a way to collect Iron (check -help Iron)"
set HelpText[i][1]= "Asteroids can be used as resource with Cargo Shuttles (buildable in Station or Shipyard Mark I)."
set HelpText[i][2]= "You just need to select a Cargo Shuttle and to right click the Asteroid."
set HelpText[i][3]= "The Cargo Shuttle will then return the Iron to the nearest Planet, Pirate Base (Pirate only) or Warehouse."
set HelpText[i][4]= "Terrorist can not use Asteroid as resource."
//! runtextmacro t__HelpSystem_Init("i","asteroid","asteroids")
set i = i + 1
//
set HelpName[i]= "Colonization"
set HelpText[i][0]= "Colonization is available for Merchants and Militaries only."
set HelpText[i][1]= "To colonize a planet, which will grants you Slots (food), you need to send a Builder Shuttle to the neutral planet target."
set HelpText[i][2]= "Then you have to use the skill of the Builder Shuttle called Colonize by targeting the planet with this skill."
set HelpText[i][3]= "This skill works only on neutral planets."
set HelpText[i][4]= "This skill is available with the research called Improved Colonization."
set HelpText[i][5]= "Higher levels of the research Improved Colonization reduces the time of the colonization."
set HelpText[i][6]= "The research Improved Colonization is available in a Research Facility - Production Center."
set HelpText[i][7]= "If the colonization is a success, you will get more Slots (food) and you will be able to build more satellites."
set HelpText[i][8]= "The other way to get planets is the Invasion."
//! runtextmacro t__HelpSystem_Init("i","colonization","colonize")
set i = i + 1
//
set HelpName[i]= "Command"
set HelpText[i][0]= "-cam XXXX"
set HelpText[i][1]= "Set the camera height to XXXX. XXXX is a number between 200 and 4000."
set HelpText[i][2]= "-ally XXXX"
set HelpText[i][3]= "-unally XXXX"
set HelpText[i][4]= "Propose an alliance/declare the war to the player XXXX."
set HelpText[i][5]= "XXXX can be a Player exact name, its number, or its color."
set HelpText[i][6]= "List: 1-red, 2-blue, 3-teal,4-purple,5-yellow,6-orange,7-green,8-pink,9-grey"
set HelpText[i][7]= "-save"
set HelpText[i][8]= "Save your experience and gives you a load Code. You can only save 3 times during a game."
set HelpText[i][9]= "-load XXXX"
set HelpText[i][10]= "Load your experience games after games. You can load it to show your experience to other players."
set HelpText[i][11]= "The Rank gives you bonus (health, damage, speed of attack and movement."
//! runtextmacro t__HelpSystem_Init("i","command","commands")
set i = i + 1
//
set HelpName[i]= "Income"
set HelpText[i][0]= "Income or Periodic Income grants resources every minute."
set HelpText[i][1]= "Income is function of the amount of food (slots) and of the Improved Iron/Pulsars Collect Research."
set HelpText[i][2]= "Some planets add an Income Bonus."
set HelpText[i][3]= "Merchants have an Income Bonus."
set HelpText[i][4]= "Merchants provide an Income Bonus with to their Alliance with their Freeport."
//! runtextmacro t__HelpSystem_Init("i","income","income")
set i = i + 1
//
set HelpName[i]= "Invasion"
set HelpText[i][0]= "Invasion is for Merchants, Militaries and Pirates only."
set HelpText[i][1]= "Invasion is the way to capture an enemy planet (not neutral one)."
set HelpText[i][2]= "To invade a planet, you need to build an Invasion Frigate - Galaxy in a Shipyard Mark II."
set HelpText[i][3]= "Then you should load troops on this Invasion Frigate thanks to a Training Center (buildable on a planet)."
set HelpText[i][4]= "When your frigate is ready, to invade, you must you the skill Invade Planet by targeting an enemy planet."
set HelpText[i][5]= "The invasion will take some time."
set HelpText[i][6]= "At the end of this time, if your offensive force is better than the defensive force of the planet, you will own it."
set HelpText[i][7]= "Capturing an enemy planet will grant you the same things as in Colonization."
set HelpText[i][8]= "Invasion grants XP for Militaries"
//! runtextmacro t__HelpSystem_Init("i","invasion","invade")
set i = i + 1
//
set HelpName[i]= "Iron"
set HelpText[i][0]="Periodic Income grants Iron for each player. Merchants have an Income bonus."
set HelpText[i][1]="All ways except terrorists can send Cargo Shuttles to harvest on Asteroids to earn more Iron."
set HelpText[i][2]="Pirates earns Iron when they attack enemies and/or capture trading ships with Harasser Frigates or Marauder Cruisers."
set HelpText[i][3]="Terrorists earns Iron when they kill enemies."
set HelpText[i][4]="Trade between freeports (or planets for merchants) grants Iron."
set HelpText[i][5]="Improved Iron Collect grants higher income and a raised power of harvest for Cargo Shuttles."
set HelpText[i][6]="Some planets raise the Periodic Income of Iron with the Improved Iron Income ability."
//! runtextmacro t__HelpSystem_Init("i","iron","lumber")
set i = i + 1
//
set HelpName[i]= "Merchant"
set HelpText[i][0]="Merchant is a way to earn a lot of cash without fighting. This way is really useful in Alliance Enabled mode, because Merchant will be able to feed its allies and develop the trade."
set HelpText[i][1]= "5% health points penalty for all units."
set HelpText[i][2]= "25% income bonus."
set HelpText[i][3]= "15% trade bonus."
set HelpText[i][4]= "Can trade with planets."
set HelpText[i][5]= "2 harvest points bonus at start for cargo shuttles."
set HelpText[i][6]= "Can choose Merchant or Polyvalent Mothership."
set HelpText[i][7]= "Special ships: Spy Cruiser: Secret Agent, Merchant Cruiser: Miserly"
set HelpText[i][8]= "Special building: Radar Tower: Guardian"
set HelpText[i][9]= "Special ability: Nanite saturation, Send Spy, Destructuration, Alliance Income Bonus"
set HelpText[i][10]= "Merchants earn XP by trading or leading researchs"
//! runtextmacro t__HelpSystem_Init("i","merchant","merchants")
set i = i + 1
//
set HelpName[i]= "Military"
set HelpText[i][0]= "Military is a long-development way, based on pure power of attack/defence and resistant ships."
set HelpText[i][1]= "10% health points bonus for all units"
set HelpText[i][2]= "Can choose Military or Polyvalent Mothership."
set HelpText[i][3]= "Special ship: Invasion Shuttle: Squareroot, Frigate: Starkiller Gunship, Invasion Cruiser: Universe"
set HelpText[i][4]= "Special Building: MicroMissiles Thrower: Typhoon"
set HelpText[i][5]= "Special ability: Derivation, MicroBlackHole, Telemetry, Self Guided Mine, Particle Shield"
set HelpText[i][6]= "Special Troop: Aircraft"
set HelpText[i][7]= "Merchants earn XP by invading planets or leading researchs"
//! runtextmacro t__HelpSystem_Init("i","military","militaries")
set i = i + 1
//
set HelpName[i]= "Mine"
set HelpText[i][0]= "Pulsars Mines are a way to collect Pulsars (check -help Pulsar)"
set HelpText[i][1]= "Pulsars Mines can be used as resource with Cargo Shuttles (buildable in Station or Shipyard Mark I)."
set HelpText[i][2]= "You just need to select a Cargo Shuttle and to right click the Pulsar Mine."
set HelpText[i][3]= "The Cargo Shuttle will then return the Pulsar to the nearest Planet, Pirate Base (Pirate only) or Warehouse."
set HelpText[i][4]= "Terrorist can not use Pulsar Mine as resource."
//! runtextmacro t__HelpSystem_Init("i","mine","mines")
set i = i + 1
//
set HelpName[i]= "Motherhip"
set HelpText[i][0]= "Motherships are upgradable and modulable ships made of a Main Body. It can be upgrade from Shuttle to Frigate and from Frigate to Cruiser"
set HelpText[i][1]= "Motherhips modules are buildable from a Dock."
set HelpText[i][2]= "If the module of the Mothership die, this will not prevent the Main Body to work."
set HelpText[i][3]= "MotherShips can be revived in the Docks"
set HelpText[i][4]= "MotherShips can be upgrade in the Docks"
//! runtextmacro t__HelpSystem_Init("i","motherhip","motherships")
set i = i + 1
//
set HelpName[i]= "Planet"
set HelpText[i][0]= "Planets are objects able to create buildings, raise your Slots (food), raise your periodic Income."
set HelpText[i][1]= "Planets can be used like Warehouse to receive the resources of the nearby Cargo Shuttles collecting resources."
set HelpText[i][2]= "Planets can be colonized if they are neutral (check -help Colonization) or invaded if they are enemy (check -help Invasion)."
set HelpText[i][3]= "Planets can be destroyed by Plasma Weapon equiped ships, like Assaut Shuttles, Assaut Frigate or Assaut Cruisers."
set HelpText[i][4]= "Planets can be assimilated by Alien with the skill Assimilation (Omega Cruiser or Alien Mothership), granting resources and Alpha Light Shuttles"
set HelpText[i][5]= "Planets are a way to increase the amount of Slots (food) you have. (check -help Slot)."
set HelpText[i][6]= "Planets grants XP to Militaries when they are invaded or to Alien when they are assimilated"
//! runtextmacro t__HelpSystem_Init("i","planet","planets")
set i = i + 1
//
set HelpName[i]= "Pirate"
set HelpText[i][0]= "Pirate is a fast-way development, to play the role of a harasser. They can be independent but will suffer problems if they only fight militaries."
set HelpText[i][1]= "20% speed of movement bonus for all units."
set HelpText[i][2]= "Resources earned by attacking other players"
set HelpText[i][3]= "Can not colonize more than one planet"
set HelpText[i][4]= "Can choose Pirate or Polyvalent Mothership"
set HelpText[i][5]= "Special ship: Frigate: Pirate Harasser, Cruiser: Pirate Marauder"
set HelpText[i][6]= "Special Building: Pirate Base"
set HelpText[i][7]= "Special ability: Afterburn, Set Up a Ionic Mine, Steal"
set HelpText[i][8]= "Pirates earn XP by attacking Cargo Shuttles, Merchant Cruisers or Merchant Motherships"
//! runtextmacro t__HelpSystem_Init("i","pirate","pirates")
set i = i + 1
//
set HelpName[i]= "Pulsar"
set HelpText[i][0]="Periodic Income grants Pulsars for each player. Merchants have an Income bonus."
set HelpText[i][1]="All ways except terrorists can send Cargo Shuttles to harves on Pulsar mines to earn more Pulsars."
set HelpText[i][2]="Pirates earn Pulsars when they attack enemies and/or capture trading ships with Harasser Frigates or Marauder Cruisers."
set HelpText[i][3]="Terrorists earn Pulsars when they kill enemies."
set HelpText[i][4]="Trade between freeports (or planets for merchants) grants Pulsars."
set HelpText[i][5]="Improved Pulsars Collect grants higher income and a raised power of harvest for Cargo Shuttles."
set HelpText[i][6]="Some planets raise the Periodic Income of Pulsars with the Improved Pulsars Income ability."
//! runtextmacro t__HelpSystem_Init("i","pulsar","gold")
set i = i + 1
//
set HelpName[i]= "Rank"
set HelpText[i][0]="Rank is a title given to a player in function of its global experience."
set HelpText[i][1]="They are up to 50 ranks to earn."
set HelpText[i][2]="Each earned rank provides a bonus of health, damage, speed of movement and attack rate to all ships. "
set HelpText[i][3]= "Rank is raised each time the experience goes higher than the required steps."
set HelpText[i][4]= "Each ways earn experience points through different means."
//! runtextmacro t__HelpSystem_Init("i","rank","grade")
set i = i + 1
//
set HelpName[i]= "Slot"
set HelpText[i][0]= "Food is called Slot in Stars. It determinates the amount of ships a Clan can build"
set HelpText[i][1]= "Colonize or invade planets raise the number of slots. Terrorist can't do this. Pirate can only colonize one planet."
set HelpText[i][2]= "Pirates can build Pirate Base to raise their Slots."
set HelpText[i][3]= "Motherships Modules MicroCity Mark I and II called Pool and Cavern can raise the amount of Slots for Merchants."
set HelpText[i][4]= "Maximum Slot amount is 150 for Merchants/Militaries/Pirates and 30 for Terrorists"
//! runtextmacro t__HelpSystem_Init("i","slot","food")
set i = i + 1
//
set HelpName[i]= "Terrorist"
set HelpText[i][0]= "Terrorist is a way centered on a unic base, the terrorist mothership. They are hard to play, and can not ally other players."
set HelpText[i][1]= "30 slots (food) maximum."
set HelpText[i][2]= "Resources earned by killing other player units and Periodic Income: no collect."
set HelpText[i][3]= "Can not colonize planet."
set HelpText[i][4]= "Only have one Terrorist Mothership as base/Mothership."
set HelpText[i][5]= "Special ship: Shuttle: Fury Cultist, Assault Shuttle: Infection, Frigate: Starkiller Gunship, Frigate: Bacillus, Frigate: Incubator, Cruiser: Aggressor"
set HelpText[i][6]= "Special research: Fear, Improved Biologic Weapons."
set HelpText[i][10]= "Terrorists earn XP by killing units"
//! runtextmacro t__HelpSystem_Init("i","terrorist","terrorists")
set i = i + 1
//
set HelpName[i]= "Trade"
set HelpText[i][0]= "Trade is a system for all ways excepted Terrorists to earn Iron and Pulsars."
set HelpText[i][1]= "To trade, you need to build a Freeport with a Builder Shuttle."
set HelpText[i][2]= "Then, you must select an allied Freeport with the Select a Buyer ability of a Cargo Shuttle."
set HelpText[i][3]= "The cargo will then fly to your freeport, load items called Products and fly to send them to the allied Freeport."
set HelpText[i][4]= "This is called a Trade road and can be stopped at any moment by using the Abort Trade ability of a cargo."
set HelpText[i][5]= "The amount of Pulsars and Iron is raised with the Distance between Freeports."
set HelpText[i][6]= "Merchants can use allied Planets instead of allied Freeport as a buyer; it is called Local Trade."
set HelpText[i][7]= "Merchants can replace Cargo Shuttles with Miserly Merchant Cruiser or Merchant Mothership."
set HelpText[i][8]= "Merchants can add MotherShip Cargo Module Mk I, II and III-called Blob,Giant and Titans- to their Motherships to raise the amount of resources earned."
set HelpText[i][9]= "Merchants have a bonus for each Trade Operation."
set HelpText[i][10]= "Merchants earn XP by trading"
//! runtextmacro t__HelpSystem_Init("i","trade","trades")
set i = i + 1
//
set HelpName[i]= "Victory"
set HelpText[i][0]= "The game is ended if you are able to destroy all of your enemies."
//! runtextmacro t__HelpSystem_Init("i","victory","win")
set i = i + 1
//
set HelpName[i]= "Way"
set HelpText[i][0]= "Ways provide specific bonus and gameplay for a player. They are like something like Race"
set HelpText[i][1]= "You choose them at the beginning of the game"
set HelpText[i][2]= "They are 5 ways: Aliens, Merchant, Military, Pirate, Terrorist"
set HelpText[i][3]= "Each way allows a player to earn experience points through different ways."
//! runtextmacro t__HelpSystem_Init("i","way","ways")
//
set HelpMax = i
endfunction
private function Conditions takes nothing returns boolean
local player whichPlayer = GetTriggerPlayer()
local string text = GetEventPlayerChatString()
local integer string_length = StringLength(text)
local integer index
local integer i = 0
if SubString(text,0,HelpCommand_length) == COM then
set text = SubString(text,HelpCommand_length+1,string_length)
if text != null then
set index = Str_table[text]
call DisplayTimedTextToPlayer(whichPlayer,0.,0.,DUR,LINE)
call DisplayTimedTextToPlayer(whichPlayer,0.,0.,DUR,"|c00AFAAFF"+HelpName[index]+"|r")
loop
exitwhen i > HelpTextMax
if HelpText[index][i]!= null then
call DisplayTimedTextToPlayer(whichPlayer,0.,0.,DUR,HelpText[index][i])
endif
set i = i + 1
endloop
else
set text = "Keywords: "
call DisplayTimedTextToPlayer(whichPlayer,0.,0.,DUR,LINE)
call DisplayTimedTextToPlayer(whichPlayer,0.,0.,DUR,NAME)
call DisplayTimedTextToPlayer(whichPlayer,0.,0.,DUR,INFO)
loop
exitwhen i > HelpMax
if HelpName[i]!= null then
set text = text+" - "+HelpName[i]
endif
set i = i + 1
endloop
call DisplayTimedTextToPlayer(whichPlayer,0.,0.,DUR,text)
call DisplayTimedTextToPlayer(whichPlayer,0.,0.,DUR,LINE)
endif
endif
set text = null
set whichPlayer = null
return false
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
set Str_table = StringTable.create()
call SetTextVariables()
set HelpCommand_length = StringLength(COM)
set i = 0
loop
exitwhen i > MAXPLAYER
call TriggerRegisterPlayerChatEvent( t, Player(i), COM, false )
set i = i + 1
endloop
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endlibrary
//TESH.scrollpos=43
//TESH.alwaysfold=0
library Income needs TimerUtils,Resource,SoundUtils
//Started in I Start trigger
globals
private constant real TIMEOUT = 60.
private constant string C1 = "|cff008040"
private constant string C2 = "|cff80FFFF"
private constant string C = " |r"
private integer Gold
private integer Lumber
private integer Bonus1
private integer Bonus2
private integer Bonus3
private integer Bonus4
endglobals
private function UpdateIncome takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = 0
local integer j = 0
call RunSound(SOUND_HINT)
loop
exitwhen i > MAXPLAYER
//Only check playing players
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING and Alien[i]==false then
//Initialize variables
set Gold = 0
set Lumber = 0
set Bonus1 = 0
set Bonus2 = 0
set Bonus3 = 0
set Bonus4 = 0
//Check Planet with Pulsar bonus
set j = 0
loop
exitwhen j > PlanetWithBonusPulsarMax
if GetOwningPlayer(PlanetWithBonusPulsar[j])==Player(i) and GetUnitState(PlanetWithBonusPulsar[j],UNIT_STATE_LIFE)>0 and PlanetWithBonusPulsar[j]!= null then
set Bonus1 = Bonus1 + 100*GetUnitAbilityLevel(PlanetWithBonusPulsar[j],PLANETINCOMEBONUS_PULSAR)
endif
set j = j + 1
endloop
//Check Planet with Iron bonus
set j = 0
loop
exitwhen j > PlanetWithBonusIronMax
if GetOwningPlayer(PlanetWithBonusIron[j])==Player(i) and GetUnitState(PlanetWithBonusIron[j],UNIT_STATE_LIFE)>0 and PlanetWithBonusIron[j]!= null then
set Bonus2 = Bonus2 + 100*GetUnitAbilityLevel(PlanetWithBonusIron[j],PLANETINCOMEBONUS_IRON)
endif
set j = j + 1
endloop
//Check Freeport bonus
//Check only if the player freeport is alive AND if he has the alliance income bonus
if GetUnitAbilityLevel(Freeport[i],'A01Y')>= 1 and Freeport[i]!= null and GetUnitState(Freeport[i],UNIT_STATE_LIFE)>0 then
set j = 0
loop
exitwhen j > MAXPLAYER
//Then check for all players if the player is allied to other and if they have a freeport
if IsPlayerAlly(Player(i),Player(j))==true and Freeport[j]!= null and GetUnitState(Freeport[j],UNIT_STATE_LIFE)>0 then
set Bonus3 = Bonus3+100
set Bonus4 = Bonus4+50
endif
set j = j + 1
endloop
endif
set Gold = 50 + GetPlayerTechCount(Player(i),'R00H',true)*25+GetPlayerState(Player(i), PLAYER_STATE_FOOD_CAP_CEILING)+Bonus1+Bonus3
set Lumber = 10 + GetPlayerTechCount(Player(i),'R00I',true)*10+R2I(0.25*GetPlayerState(Player(i), PLAYER_STATE_FOOD_CAP_CEILING)) +Bonus2+Bonus4
if Merchant[GetPlayerId(Player(i))]== true then
set Gold = R2I(1.25*Gold)
set Lumber = R2I(1.25*Lumber)
endif
if Terrorist[GetPlayerId(Player(i))]== true then
set Gold = R2I(4.00*Gold)
set Lumber = R2I(10.00*Lumber)
endif
call SetResource(Player(i),Gold,Lumber)
call DisplayTextToPlayer( Player(i), 0, 0, "Income: "+C1+I2S(Gold)+C+" pulsars and " +C2+I2S(Lumber)+C+" Iron")
if Merchant[GetPlayerId(Player(i))]== true then
call DisplayTextToPlayer( Player(i), 0, 0, "Included Merchand Bonus: "+C1+I2S(R2I(0.25*Gold))+C+" Pulsars and " +C2+I2S(R2I(0.25*Lumber))+C+" Iron" )
endif
if Bonus1 > 0 or Bonus2 > 0 then
call DisplayTextToPlayer( Player(i), 0, 0, "Included Planets Bonus: "+C1+I2S(Bonus1)+C+" Pulsars and " +C2+I2S(Bonus2)+C+" Iron")
endif
if Bonus3 > 0 or Bonus4 > 0 then
call DisplayTextToPlayer( Player(i), 0, 0, "Included Allied Freeport Bonus: "+C1+I2S(Bonus3)+C+" Pulsars and " +C2+I2S(Bonus4)+C+" Iron")
endif
endif
set i = i + 1
endloop
endfunction
function RunIncome takes nothing returns nothing
local timer t = NewTimer()
call TimerStart (t, TIMEOUT, true, function UpdateIncome )
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library PlayerLeaveDetection needs SoundUtils, TextDisplay, GroupFunction, BoardSystem, TimerUtils
globals //Trigger enabled in the Set Modes and Start Trigger to prevent loading bugs
private constant string MESSAGE = "has left the game."
endglobals
private function GameEnd takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = 0
call ReleaseTimer(t)
loop
exitwhen i > MAXPLAYER
call CustomVictoryBJ(Player(i), true, true )
set i = i + 1
endloop
endfunction
private function TheGameWillEnd takes nothing returns nothing
local timer t = NewTimer()
local integer i = 0
call DisplayAll("Game", "You are the last player alive! You won!")
set i = 0
loop
exitwhen i > MAXPLAYER
call KillAllUnitsOfPlayer(Player(i))
call UpdateRank(Player(i),100)
set i = i + 1
endloop
call DisplayAll("Game","90 seconds before the end of a game. You should save your experience with the -save command." )
call TimerStart(t,90.,false,function GameEnd)
endfunction
private function CheckAmountOfPlayerLeft takes nothing returns boolean
local integer i = 0
local integer amount = 0
loop
exitwhen i > MAXPLAYER
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
set amount = amount + 1
endif
set i = i + 1
endloop
return amount <= 1
endfunction
private function PlayerHasLeft takes nothing returns boolean
local integer i = 0
local integer amount = 0
local player whichPlayer = GetTriggerPlayer()
local integer whichPlayerId = GetPlayerId(whichPlayer)
//End the player units and display message to other players
call RunSound(SOUND_HINT)
call DisplayAll("Game", PlayerColor[GetPlayerId(whichPlayer)] + GetPlayerName(whichPlayer) + MESSAGE)
call KillAllUnitsOfPlayer(whichPlayer)
call LeaderboardSetItemLabel(Board,LeaderboardGetPlayerIndex(Board,whichPlayer),"<left>")
//Grants an alliance free slots for staying player which were allied to the leaver
set i = 0
loop
exitwhen i > MAXPLAYER
if IsPlayerAlly(whichPlayer,Player(i))==true then
set PlayerAllies[i]= PlayerAllies[i] - 1
endif
endloop
//If one player left, victory to this player
if CheckAmountOfPlayerLeft() then
call TheGameWillEnd()
endif
set whichPlayer = null
return false
endfunction
function EnablePlayerLeaveDetection takes nothing returns nothing
local integer i = 0
local trigger t = CreateTrigger()
loop
exitwhen i > MAXPLAYER
call TriggerRegisterPlayerEventLeave(t, Player(i) )
set i = i + 1
endloop
call TriggerAddCondition(t,Condition(function PlayerHasLeft))
endfunction
endlibrary
//TESH.scrollpos=147
//TESH.alwaysfold=0
library MsSys initializer init requires Table, TimerUtils,AutoIndex, BoundSentinel, AbilityPreload,SpellEvent,TextDisplay
globals
private constant real TIMEOUT = 0.05
private constant integer CARGO1 = 'E010'
private constant integer CARGO2 = 'E011'
private constant integer CARGO3 = 'E012'
private constant integer MST0 = 'H02G'
private constant string C1 = "You already have the maximum number of modules allowed with this ship."
private constant string C2 = "Distance between the dock and the Mothership must be less than "
private constant string C3 = " to get the new module. Current Range: "
private constant string C4 = "Modules slot left for your Mothership: "
private constant real RANGE = 300.00
private constant integer MAXMODSHUT = 2
private constant integer MAXMODFRIG = 4
private constant integer MAXMODCRUIZ = 6
unit array MotherShip [12]
integer array TmpMod1 [12]
integer array TmpMod2 [12]
integer array TmpMod3 [12]
integer array TmpMod4 [12]
integer array TmpMod5 [12]
integer array TmpMod6 [12]
private constant integer UpToFrig ='R00Z'
private constant integer UpToCruiz ='R010'
private constant integer HasShut = 'R00W'
private constant integer HasFrig = 'R00X'
private constant integer HasCruiz ='R00Y'
private constant integer ISMSMOD = 'A03X'
private key INDEX_ANGLE1
private key INDEX_ANGLE2
private key INDEX_ANGLE3
private key INDEX_ANGLE4
private key INDEX_ANGLE5
private key INDEX_ANGLE6
private key INDEX_HEIGH
private key INDEX_UPGRADE
private key INDEX_DISTANCE1
private key INDEX_DISTANCE2
private key INDEX_DISTANCE3
private key INDEX_DISTANCE4
private key INDEX_DISTANCE5
private key INDEX_DISTANCE6
private key INDEX_SKILL
private key INDEX_CLASS //1=shut, 2=frig, 3==Cruis
private hashtable HashT
endglobals
//! textmacro t__ModulePosition_Init takes MS ,CLASS, UPGRADE ,HEIGHT , A1, A2, A3, A4, A5, A6, D1, D2, D3, D4, D5, D6
call SaveInteger(HashT,$MS$,INDEX_CLASS,$CLASS$)
call SaveInteger(HashT,$MS$,INDEX_UPGRADE,$UPGRADE$)
call SaveInteger(HashT,$MS$,INDEX_HEIGH,$HEIGHT$)
call SaveInteger(HashT,$MS$,INDEX_ANGLE1,$A1$)
call SaveInteger(HashT,$MS$,INDEX_ANGLE2,$A2$)
call SaveInteger(HashT,$MS$,INDEX_ANGLE3,$A3$)
call SaveInteger(HashT,$MS$,INDEX_ANGLE4,$A4$)
call SaveInteger(HashT,$MS$,INDEX_ANGLE5,$A5$)
call SaveInteger(HashT,$MS$,INDEX_ANGLE6,$A6$)
call SaveInteger(HashT,$MS$,INDEX_DISTANCE1,$D1$)
call SaveInteger(HashT,$MS$,INDEX_DISTANCE2,$D2$)
call SaveInteger(HashT,$MS$,INDEX_DISTANCE3,$D3$)
call SaveInteger(HashT,$MS$,INDEX_DISTANCE4,$D4$)
call SaveInteger(HashT,$MS$,INDEX_DISTANCE5,$D5$)
call SaveInteger(HashT,$MS$,INDEX_DISTANCE6,$D6$)
//! endtextmacro
//! textmacro t__ModuleSkill_Init takes MOD ,SKILL
call SaveInteger(HashT,$MOD$,INDEX_SKILL,$SKILL$)
call AbilityPreload($SKILL$)
//! endtextmacro
private function SetVariables takes nothing returns nothing
local integer i = 0
//! runtextmacro t__ModulePosition_Init("'H02E'","1","'H02H'","5","0","0","0","0","0","0","-10","0","0","0","0","0")
//! runtextmacro t__ModulePosition_Init("'H02D'","1","'H02N'","5","0","0","0","0","0","0","-10","10","0","0","0","0")
//! runtextmacro t__ModulePosition_Init("'H02F'","1","'H02O'","6","0","0","0","0","0","0","15","0","0","0","0","0")
//! runtextmacro t__ModulePosition_Init("'H02C'","1","'H02K'","5","90","0","0","0","0","0","10","10","0","0","0","0")
//! runtextmacro t__ModulePosition_Init("'H02H'","2","'H02M'","10","180","180","180","0","0","0","10","0","20","10","0","0")
//! runtextmacro t__ModulePosition_Init("'H02N'","2","'H02L'","20","0","180","180","0","0","0","0","13","25","13","0","0")
//! runtextmacro t__ModulePosition_Init("'H02O'","2","'H02I'","5","180","180","180","180","0","0","0","13","25","38","0","0")
//! runtextmacro t__ModulePosition_Init("'H02K'","2","'H02J'","10","0","45","-45","-315","0","0","0","13","13","13","0","0")
//! runtextmacro t__ModulePosition_Init("'H02M'","3","'XXXX'","15","0","0","0","0","0","0","0","10","15","20","25","30")
//! runtextmacro t__ModulePosition_Init("'H02L'","3","'XXXX'","30","0","180","45","-45","225","-225","0","10","25","25","25","25")
//! runtextmacro t__ModulePosition_Init("'H02I'","3","'XXXX'","20","0","180","45","-45","315","-315","25","25","25","25","25","25")
//! runtextmacro t__ModulePosition_Init("'H02J'","3","'XXXX'","25","0","0","45","-45","90","-90","0","13","18","13","13","13")
//! runtextmacro t__ModuleSkill_Init("'E004'","'A00O'")
//! runtextmacro t__ModuleSkill_Init("'E005'","'A00P'")
//! runtextmacro t__ModuleSkill_Init("'E013'","'A01W'")
//! runtextmacro t__ModuleSkill_Init("'E014'","'A000'")
//! runtextmacro t__ModuleSkill_Init("'E024'","'A033'")
//! runtextmacro t__ModuleSkill_Init("'E028'","'A00L'")
//! runtextmacro t__ModuleSkill_Init("'E029'","'A00N'")
//! runtextmacro t__ModuleSkill_Init("'E030'","'A00M'")
//! runtextmacro t__ModuleSkill_Init("'E032'","'A034'")
//! runtextmacro t__ModuleSkill_Init("'E035'","'A035'")
endfunction
private struct s_MsSys
player owner = null
unit ms = null
integer msId = 0
integer ownerId = 0
timer ti = null
integer countmod = 0
unit mod1 = null
unit mod2 = null
unit mod3 = null
unit mod4 = null
unit mod5 = null
unit mod6 = null
real a1 = 0.
real a2 = 0.
real a3 = 0.
real a4 = 0.
real a5 = 0.
real a6 = 0.
real d1 = 0.
real d2 = 0.
real d3 = 0.
real d4 = 0.
real d5 = 0.
real d6 = 0.
private static method createFilter takes unit u returns boolean
return IsUnitType(u,UNIT_TYPE_HERO) and GetUnitAbilityLevel(u,ISMSMOD)<=0 and GetUnitTypeId(u)!=MST0 and GetUnitTypeId(u)!=DUMMYPICK
endmethod
private method onCreate takes nothing returns nothing
set .ms = me
set .owner = GetOwningPlayer(.ms)
set .ownerId = GetPlayerId(.owner)
set MotherShip[.ownerId] = me
set .msId = GetUnitTypeId(.ms)
set .ti = null
set .countmod = 0
set .a1 = LoadInteger(HashT,GetUnitTypeId(.ms),INDEX_ANGLE1)
set .a2 = LoadInteger(HashT,GetUnitTypeId(.ms),INDEX_ANGLE2)
set .a3 = LoadInteger(HashT,GetUnitTypeId(.ms),INDEX_ANGLE3)
set .a4 = LoadInteger(HashT,GetUnitTypeId(.ms),INDEX_ANGLE4)
set .a5 = LoadInteger(HashT,GetUnitTypeId(.ms),INDEX_ANGLE5)
set .a6 = LoadInteger(HashT,GetUnitTypeId(.ms),INDEX_ANGLE6)
set .d1 = LoadInteger(HashT,GetUnitTypeId(.ms),INDEX_DISTANCE1)
set .d2 = LoadInteger(HashT,GetUnitTypeId(.ms),INDEX_DISTANCE2)
set .d3 = LoadInteger(HashT,GetUnitTypeId(.ms),INDEX_DISTANCE3)
set .d4 = LoadInteger(HashT,GetUnitTypeId(.ms),INDEX_DISTANCE4)
set .d5 = LoadInteger(HashT,GetUnitTypeId(.ms),INDEX_DISTANCE5)
set .d6 = LoadInteger(HashT,GetUnitTypeId(.ms),INDEX_DISTANCE6)
set .mod1 = null
set .mod2 = null
set .mod3 = null
set .mod4 = null
set .mod5 = null
set .mod6 = null
endmethod
implement AutoCreate
private method onDestroy takes nothing returns nothing
set .ms = null
set .owner = null
set .msId = 0
call ReleaseTimer(.ti)
set .ti = null
set .countmod = 0
set .mod1 = null
set .mod2 = null
set .mod3 = null
set .mod4 = null
set .mod5 = null
set .mod6 = null
endmethod
implement AutoDestroy
endstruct
private function CancelMod takes unit mod returns nothing
local s_MsSys dat = s_MsSys[MotherShip[GetPlayerId(GetOwningPlayer(mod))]]
call UnitRemoveAbility(dat.ms,LoadInteger(HashT,GetUnitTypeId(mod),INDEX_SKILL))
call RemoveUnit(mod)
set dat.countmod = dat.countmod - 1
endfunction
private function UpdateModulePosition takes nothing returns nothing
local timer t = GetExpiredTimer()
local s_MsSys dat = GetTimerData(t)
local real x1 = GetUnitX(dat.ms)
local real y1 = GetUnitY(dat.ms)
local real facing = GetUnitFacing(dat.ms)
if not (IsUnitType(dat.mod1,UNIT_TYPE_DEAD)) and dat.mod1 != null then
call SetUnitX(dat.mod1,x1+dat.d1*Cos((facing + dat.a1)*bj_DEGTORAD) )
call SetUnitY(dat.mod1,y1+dat.d1*Sin((facing + dat.a1)*bj_DEGTORAD) )
if IsUnitType(dat.mod1,UNIT_TYPE_TAUREN) then
call SetUnitFacing(dat.mod1,facing)
endif
else
if dat.mod1 != null then
call CancelMod(dat.mod1)
set dat.mod1 = null
endif
endif
if not (IsUnitType(dat.mod2,UNIT_TYPE_DEAD)) and dat.mod2 != null then
call SetUnitX(dat.mod2,x1+dat.d2*Cos((facing + dat.a2)*bj_DEGTORAD) )
call SetUnitY(dat.mod2,y1+dat.d2*Sin((facing + dat.a2)*bj_DEGTORAD) )
if IsUnitType(dat.mod2,UNIT_TYPE_TAUREN) then
call SetUnitFacing(dat.mod2,facing)
endif
else
if dat.mod2 != null then
call CancelMod(dat.mod2)
set dat.mod2 = null
endif
endif
if not (IsUnitType(dat.mod3,UNIT_TYPE_DEAD))and dat.mod3 != null then
call SetUnitX(dat.mod3,x1+dat.d3*Cos((facing + dat.a3)*bj_DEGTORAD) )
call SetUnitY(dat.mod3,y1+dat.d3*Sin((facing + dat.a3)*bj_DEGTORAD) )
if IsUnitType(dat.mod3,UNIT_TYPE_TAUREN) then
call SetUnitFacing(dat.mod3,facing)
endif
else
if dat.mod3 != null then
call CancelMod(dat.mod3)
set dat.mod3 = null
endif
endif
if not (IsUnitType(dat.mod5,UNIT_TYPE_DEAD))and dat.mod4 != null then
call SetUnitX(dat.mod4,x1+dat.d4*Cos((facing + dat.a4)*bj_DEGTORAD) )
call SetUnitY(dat.mod4,y1+dat.d4*Sin((facing + dat.a4)*bj_DEGTORAD) )
if IsUnitType(dat.mod4,UNIT_TYPE_TAUREN) then
call SetUnitFacing(dat.mod4,facing)
endif
else
if dat.mod4 != null then
call CancelMod(dat.mod4)
set dat.mod4 = null
endif
endif
if not (IsUnitType(dat.mod5,UNIT_TYPE_DEAD)) and dat.mod5 != null then
call SetUnitX(dat.mod5,x1+dat.d5*Cos((facing + dat.a5)*bj_DEGTORAD) )
call SetUnitY(dat.mod5,y1+dat.d5*Sin((facing + dat.a5)*bj_DEGTORAD) )
if IsUnitType(dat.mod5,UNIT_TYPE_TAUREN) then
call SetUnitFacing(dat.mod5,facing)
endif
else
if dat.mod5 != null then
call CancelMod(dat.mod5)
set dat.mod5 = null
endif
endif
if not (IsUnitType(dat.mod6,UNIT_TYPE_DEAD)) and dat.mod6 != null then
call SetUnitX(dat.mod6,x1+dat.d6*Cos((facing + dat.a6)*bj_DEGTORAD) )
call SetUnitY(dat.mod6,y1+dat.d6*Sin((facing + dat.a6)*bj_DEGTORAD) )
if IsUnitType(dat.mod6,UNIT_TYPE_TAUREN) then
call SetUnitFacing(dat.mod6,facing)
endif
else
if dat.mod6 != null then
call CancelMod(dat.mod6)
set dat.mod6 = null
endif
endif
endfunction
private function LinkMod takes unit mod returns nothing
local s_MsSys dat = s_MsSys[MotherShip[GetPlayerId(GetOwningPlayer(mod))]]
call SetUnitPathing(mod,false)
call SetUnitFlyHeight(mod,GetUnitFlyHeight(dat.ms)+LoadInteger(HashT,GetUnitTypeId(dat.ms),INDEX_HEIGH),0.)
if dat.mod1 == null then
set dat.mod1 = mod
set dat.countmod = dat.countmod + 1
return
elseif dat.mod2 == null then
set dat.mod2 = mod
set dat.countmod = dat.countmod + 1
return
elseif dat.mod3 == null then
set dat.mod3 = mod
set dat.countmod = dat.countmod + 1
return
elseif dat.mod4 == null then
set dat.mod4 = mod
set dat.countmod = dat.countmod + 1
return
elseif dat.mod5 == null then
set dat.mod5 = mod
set dat.countmod = dat.countmod + 1
return
elseif dat.mod6 == null then
set dat.mod6 = mod
set dat.countmod = dat.countmod + 1
return
endif
endfunction
function CountCargoMod takes unit ms returns integer
local integer value = 0
local s_MsSys dat = s_MsSys[ms]
if not (IsUnitType(dat.mod1, UNIT_TYPE_DEAD)) then
if GetUnitTypeId(dat.mod1) == CARGO1 then
set value = value + 1
elseif GetUnitTypeId(dat.mod1) == CARGO2 then
set value = value + 2
elseif GetUnitTypeId(dat.mod1) == CARGO3 then
set value = value + 3
endif
endif
if not (IsUnitType(dat.mod2, UNIT_TYPE_DEAD)) then
if GetUnitTypeId(dat.mod2) == CARGO1 then
set value = value + 1
elseif GetUnitTypeId(dat.mod2) == CARGO2 then
set value = value + 2
elseif GetUnitTypeId(dat.mod2) == CARGO3 then
set value = value + 3
endif
endif
if not (IsUnitType(dat.mod3, UNIT_TYPE_DEAD)) then
if GetUnitTypeId(dat.mod3) == CARGO1 then
set value = value + 1
elseif GetUnitTypeId(dat.mod3) == CARGO2 then
set value = value + 2
elseif GetUnitTypeId(dat.mod3) == CARGO3 then
set value = value + 3
endif
endif
if not (IsUnitType(dat.mod4, UNIT_TYPE_DEAD)) then
if GetUnitTypeId(dat.mod4) == CARGO1 then
set value = value + 1
elseif GetUnitTypeId(dat.mod4) == CARGO2 then
set value = value + 2
elseif GetUnitTypeId(dat.mod4) == CARGO3 then
set value = value + 3
endif
endif
if not (IsUnitType(dat.mod5, UNIT_TYPE_DEAD)) then
if GetUnitTypeId(dat.mod5) == CARGO1 then
set value = value + 1
elseif GetUnitTypeId(dat.mod5) == CARGO2 then
set value = value + 2
elseif GetUnitTypeId(dat.mod5) == CARGO3 then
set value = value + 3
endif
endif
if not (IsUnitType(dat.mod6, UNIT_TYPE_DEAD)) then
if GetUnitTypeId(dat.mod6) == CARGO1 then
set value = value + 1
elseif GetUnitTypeId(dat.mod6) == CARGO2 then
set value = value + 2
elseif GetUnitTypeId(dat.mod6) == CARGO3 then
set value = value + 3
endif
endif
return value
endfunction
private function ChangeMod takes unit modbase, unit modnew returns nothing
local s_MsSys dat = s_MsSys[MotherShip[GetPlayerId(GetOwningPlayer(modnew))]]
if dat.mod1 == modbase then
set dat.mod1 = modnew
elseif dat.mod2 == modbase then
set dat.mod2 = modnew
elseif dat.mod3 == modbase then
set dat.mod3 = modnew
elseif dat.mod4 == modbase then
set dat.mod4 = modnew
elseif dat.mod5 == modbase then
set dat.mod5 = modnew
elseif dat.mod6 == modbase then
set dat.mod6 = modnew
endif
call RemoveUnit(modbase)
call UnitAddAbility(dat.ms,LoadInteger(HashT,GetUnitTypeId(modnew),INDEX_SKILL))
call SetUnitFlyHeight(modnew,GetUnitFlyHeight(dat.ms)+LoadInteger(HashT,GetUnitTypeId(dat.ms),INDEX_HEIGH),0.)
call SetUnitPathing(modnew,false)
endfunction
private function InitializeTimer takes unit ms returns nothing
local s_MsSys dat = s_MsSys[ms]
if dat.ti == null then
set dat.ti = NewTimer()
call SetTimerData( dat.ti, dat )
call TimerStart( dat.ti, TIMEOUT, true, function UpdateModulePosition )
endif
endfunction
private function TransferMods takes unit ms returns nothing
local s_MsSys dat = s_MsSys[ms]
local unit tmpMod = null
if TmpMod1[dat.ownerId]!= 0 then
set tmpMod = CreateUnit(dat.owner,TmpMod1[dat.ownerId],GetUnitX(dat.ms),GetUnitY(dat.ms),0.)
set dat.mod1 = tmpMod
call UnitAddAbility(dat.ms,LoadInteger(HashT,GetUnitTypeId(tmpMod),INDEX_SKILL))
call SetUnitFlyHeight(tmpMod,GetUnitFlyHeight(dat.ms)+LoadInteger(HashT,GetUnitTypeId(dat.ms),INDEX_HEIGH),0.)
call SetUnitPathing(tmpMod,false)
set dat.countmod = dat.countmod + 1
endif
if TmpMod2[dat.ownerId]!= 0 then
set tmpMod = CreateUnit(dat.owner,TmpMod2[dat.ownerId],GetUnitX(dat.ms),GetUnitY(dat.ms),0.)
set dat.mod2 = tmpMod
call UnitAddAbility(dat.ms,LoadInteger(HashT,GetUnitTypeId(tmpMod),INDEX_SKILL))
call SetUnitFlyHeight(tmpMod,GetUnitFlyHeight(dat.ms)+LoadInteger(HashT,GetUnitTypeId(dat.ms),INDEX_HEIGH),0.)
call SetUnitPathing(tmpMod,false)
set dat.countmod = dat.countmod + 1
endif
if TmpMod3[dat.ownerId]!= 0 then
set tmpMod = CreateUnit(dat.owner,TmpMod3[dat.ownerId],GetUnitX(dat.ms),GetUnitY(dat.ms),0.)
set dat.mod3 = tmpMod
call UnitAddAbility(dat.ms,LoadInteger(HashT,GetUnitTypeId(tmpMod),INDEX_SKILL))
call SetUnitFlyHeight(tmpMod,GetUnitFlyHeight(dat.ms)+LoadInteger(HashT,GetUnitTypeId(dat.ms),INDEX_HEIGH),0.)
call SetUnitPathing(tmpMod,false)
set dat.countmod = dat.countmod + 1
endif
if TmpMod4[dat.ownerId]!= 0 then
set tmpMod = CreateUnit(dat.owner,TmpMod4[dat.ownerId],GetUnitX(dat.ms),GetUnitY(dat.ms),0.)
set dat.mod4 = tmpMod
call UnitAddAbility(dat.ms,LoadInteger(HashT,GetUnitTypeId(tmpMod),INDEX_SKILL))
call SetUnitFlyHeight(tmpMod,GetUnitFlyHeight(dat.ms)+LoadInteger(HashT,GetUnitTypeId(dat.ms),INDEX_HEIGH),0.)
call SetUnitPathing(tmpMod,false)
set dat.countmod = dat.countmod + 1
endif
if TmpMod5[dat.ownerId]!= 0 then
set tmpMod = CreateUnit(dat.owner,TmpMod5[dat.ownerId],GetUnitX(dat.ms),GetUnitY(dat.ms),0.)
set dat.mod5 = tmpMod
call UnitAddAbility(dat.ms,LoadInteger(HashT,GetUnitTypeId(tmpMod),INDEX_SKILL))
call SetUnitFlyHeight(tmpMod,GetUnitFlyHeight(dat.ms)+LoadInteger(HashT,GetUnitTypeId(dat.ms),INDEX_HEIGH),0.)
call SetUnitPathing(tmpMod,false)
set dat.countmod = dat.countmod + 1
endif
if TmpMod6[dat.ownerId]!= 0 then
set tmpMod = CreateUnit(dat.owner,TmpMod6[dat.ownerId],GetUnitX(dat.ms),GetUnitY(dat.ms),0.)
set dat.mod6 = tmpMod
call UnitAddAbility(dat.ms,LoadInteger(HashT,GetUnitTypeId(tmpMod),INDEX_SKILL))
call SetUnitFlyHeight(tmpMod,GetUnitFlyHeight(dat.ms)+LoadInteger(HashT,GetUnitTypeId(dat.ms),INDEX_HEIGH),0.)
call SetUnitPathing(tmpMod,false)
set dat.countmod = dat.countmod + 1
endif
endfunction
private function Upgrade takes unit ms returns nothing
local s_MsSys dat = s_MsSys[ms]
local real x = GetUnitX(dat.ms)
local real y = GetUnitY(dat.ms)
local real a = GetUnitFacing(dat.ms)
local integer j = 0
local unit tmpMs = null
if not (IsUnitType(dat.mod1,UNIT_TYPE_DEAD)) then
set TmpMod1[dat.ownerId] = GetUnitTypeId(dat.mod1)
else
set TmpMod1[dat.ownerId] = 0
endif
if not (IsUnitType(dat.mod2,UNIT_TYPE_DEAD)) then
set TmpMod2[dat.ownerId] = GetUnitTypeId(dat.mod2)
else
set TmpMod2[dat.ownerId] = 0
endif
if not (IsUnitType(dat.mod3,UNIT_TYPE_DEAD)) then
set TmpMod3[dat.ownerId] = GetUnitTypeId(dat.mod3)
else
set TmpMod3[dat.ownerId] = 0
endif
if not (IsUnitType(dat.mod4,UNIT_TYPE_DEAD)) then
set TmpMod4[dat.ownerId] = GetUnitTypeId(dat.mod4)
else
set TmpMod4[dat.ownerId] = 0
endif
if not (IsUnitType(dat.mod5,UNIT_TYPE_DEAD)) then
set TmpMod5[dat.ownerId] = GetUnitTypeId(dat.mod5)
else
set TmpMod5[dat.ownerId] = 0
endif
if not (IsUnitType(dat.mod6,UNIT_TYPE_DEAD)) then
set TmpMod6[dat.ownerId] = GetUnitTypeId(dat.mod6)
else
set TmpMod6[dat.ownerId] = 0
endif
call RemoveUnit(dat.mod1)
call RemoveUnit(dat.mod2)
call RemoveUnit(dat.mod3)
call RemoveUnit(dat.mod4)
call RemoveUnit(dat.mod5)
call RemoveUnit(dat.mod6)
set dat.mod1 = null
set dat.mod2 = null
set dat.mod3 = null
set dat.mod4 = null
set dat.mod5 = null
set dat.mod6 = null
set tmpMs = CreateUnit(dat.owner,LoadInteger(HashT,dat.msId,INDEX_UPGRADE),x,y,a)
call RemoveUnit(dat.ms)
call TransferMods(tmpMs)
call InitializeTimer(tmpMs)
set tmpMs = null
endfunction
private function AddModule takes nothing returns boolean
local unit dockOrBaseMod = GetTriggerUnit()
local unit mod = GetTrainedUnit()
local s_MsSys dat = s_MsSys[MotherShip[GetPlayerId(GetOwningPlayer(mod))]]
local real x1 = GetUnitX(dat.ms)
local real y1 = GetUnitY(dat.ms)
local real x2 = GetUnitX(dockOrBaseMod)
local real y2 = GetUnitY(dockOrBaseMod)
local real distance = SquareRoot((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
if GetUnitTypeId(mod)==MST0 then
if LoadInteger(HashT,dat.msId,INDEX_CLASS) == 1 then //Shuttle
if dat.countmod < MAXMODSHUT and distance<= RANGE then
call LinkMod(mod)
call DisplayTextToPlayer(dat.owner,0,0,C4+I2S(MAXMODSHUT-dat.countmod))
elseif dat.countmod >= MAXMODSHUT then
call ErrorSound(dat.owner)
call DisplayTextToPlayer(dat.owner,0,0,C1)
call RemoveUnit(mod)
elseif distance > RANGE then
call ErrorSound(dat.owner)
call DisplayTextToPlayer(dat.owner,0,0,C2+I2S(R2I(RANGE))+C3+I2S(R2I(distance)))
call RemoveUnit(mod)
endif
elseif LoadInteger(HashT,dat.msId,INDEX_CLASS) == 2 then //Frigate
if dat.countmod < MAXMODFRIG and distance<= RANGE then
call LinkMod(mod)
call DisplayTextToPlayer(dat.owner,0,0,C4+I2S(MAXMODFRIG-dat.countmod))
elseif dat.countmod >= MAXMODFRIG then
call ErrorSound(dat.owner)
call DisplayTextToPlayer(dat.owner,0,0,C1)
call RemoveUnit(mod)
elseif distance > RANGE then
call ErrorSound(dat.owner)
call DisplayTextToPlayer(dat.owner,0,0,C2+I2S(R2I(RANGE))+C3+I2S(R2I(distance)))
call RemoveUnit(mod)
endif
elseif LoadInteger(HashT,dat.msId,INDEX_CLASS) == 3 then //Cruiser
if dat.countmod < MAXMODCRUIZ and distance<= RANGE then
call LinkMod(mod)
call DisplayTextToPlayer(dat.owner,0,0,C4+I2S(MAXMODCRUIZ-dat.countmod))
elseif dat.countmod >= MAXMODCRUIZ then
call ErrorSound(dat.owner)
call DisplayTextToPlayer(dat.owner,0,0,C1)
call RemoveUnit(mod)
elseif distance > RANGE then
call ErrorSound(dat.owner)
call DisplayTextToPlayer(dat.owner,0,0,C2+I2S(R2I(RANGE))+C3+I2S(R2I(distance)))
call RemoveUnit(mod)
endif
elseif LoadInteger(HashT,dat.msId,INDEX_CLASS) <1 or LoadInteger(HashT,dat.msId,INDEX_CLASS) >3 then
call BJDebugMsg("Mothership bug for player "+I2S(dat.ownerId)+ " The mothership class is unknown")
endif
elseif GetUnitAbilityLevel(mod,ISMSMOD)>=1 and GetUnitTypeId(mod)!=MST0 then
call ChangeMod(dockOrBaseMod,mod)
endif
set dockOrBaseMod = null
set mod = null
return false
endfunction
private function DisableMerMods takes player whichPlayer returns nothing
//Cargo Modules Mk1, 2 and 3
call SetPlayerTechMaxAllowed(whichPlayer,'E010',0)
call SetPlayerTechMaxAllowed(whichPlayer,'E011',0)
call SetPlayerTechMaxAllowed(whichPlayer,'E012',0)
//Microcities Mk1 and 2
call SetPlayerTechMaxAllowed(whichPlayer,'E019',0)
call SetPlayerTechMaxAllowed(whichPlayer,'E020',0)
endfunction
private function DisableMilMods takes player whichPlayer returns nothing
//MicroBH
call SetPlayerTechMaxAllowed(whichPlayer,'E006',0)
//MicroMis Thrower Mk2
call SetPlayerTechMaxAllowed(whichPlayer,'E022',0)
//Tank Module
call SetPlayerTechMaxAllowed(whichPlayer,'E033',0)
//Torpedo Launcher
call SetPlayerTechMaxAllowed(whichPlayer,'E034',0)
endfunction
private function DisablePirMods takes player whichPlayer returns nothing
//Afterburner mk2
call SetPlayerTechMaxAllowed(whichPlayer,'E005',0)
//boarder
call SetPlayerTechMaxAllowed(whichPlayer,'E007',0)
//hyperforcer
call SetPlayerTechMaxAllowed(whichPlayer,'E013',0)
//Secondary motor Mark 3
call SetPlayerTechMaxAllowed(whichPlayer,'E030',0)
endfunction
private function DisablePolMods takes player whichPlayer returns nothing
//Builder
call SetPlayerTechMaxAllowed(whichPlayer,'E009',0)
//Reparator
call SetPlayerTechMaxAllowed(whichPlayer,'E027',0)
endfunction
private function IniMs takes player whichPlayer,unit mothership returns nothing
local integer whichPlayerId = GetPlayerId(whichPlayer)
local real x = GetUnitX(mothership)
local real y = GetUnitY(mothership)
local unit dummy = null
call SetPlayerTechResearched(whichPlayer, HasShut, 1 )
//Give it the instant colo ability
call UnitAddAbility(mothership,'A007')
//Create the dummy with start buffs
set dummy= CreateUnit(whichPlayer,'o00L',x,y,0.)
call UnitApplyTimedLife(dummy,'BTLF',5.)
call IssueTargetOrder(dummy,"innerfire", mothership)
call IssueTargetOrder(dummy,"bloodlust", mothership)
call IssueImmediateOrder(mothership,"divineshield")
//Selet the MS
if whichPlayer == GetLocalPlayer() then
call ClearSelection()
call SelectUnit(mothership,true)
endif
//Initialize the Ms system
call InitializeTimer(mothership)
call RemoveUnit(FirstShip[whichPlayerId])
set dummy = null
endfunction
private function MsMer takes nothing returns nothing
//This trigger should work only for shuttle motherships
local unit mothership = SpellEvent.CastingUnit
local player owner = GetOwningPlayer(mothership) //The first ship
local real x = GetUnitX(mothership)
local real y = GetUnitY(mothership)
set mothership = CreateUnit(owner,'H02E',x,y,0.)
call DisableMilMods(owner)
call DisablePirMods(owner)
call DisablePolMods(owner)
call IniMs(owner,mothership)
set mothership = null
set owner = null
endfunction
private function MsMil takes nothing returns nothing
//This trigger should work only for shuttle motherships
local unit mothership = SpellEvent.CastingUnit
local player owner = GetOwningPlayer(mothership) //The first ship
local real x = GetUnitX(mothership)
local real y = GetUnitY(mothership)
set mothership = CreateUnit(owner,'H02D',x,y,0.)
call DisableMerMods(owner)
call DisablePirMods(owner)
call DisablePolMods(owner)
call IniMs(owner,mothership)
set mothership = null
set owner = null
endfunction
private function MsPir takes nothing returns nothing
//This trigger should work only for shuttle motherships
local unit mothership = SpellEvent.CastingUnit
local player owner = GetOwningPlayer(mothership) //The first ship
local real x = GetUnitX(mothership)
local real y = GetUnitY(mothership)
set mothership = CreateUnit(owner,'H02F',x,y,0.)
call DisableMerMods(owner)
call DisableMilMods(owner)
call DisablePolMods(owner)
call IniMs(owner,mothership)
set mothership = null
set owner = null
endfunction
private function MsPol takes nothing returns nothing
//This trigger should work only for shuttle motherships
local unit mothership = SpellEvent.CastingUnit
local player owner = GetOwningPlayer(mothership) //The first ship
local real x = GetUnitX(mothership)
local real y = GetUnitY(mothership)
set mothership = CreateUnit(owner,'H02C',x,y,0.)
call DisableMerMods(owner)
call DisableMilMods(owner)
call DisablePirMods(owner)
call IniMs(owner,mothership)
set mothership = null
set owner = null
endfunction
private function UpgradeMainBody takes nothing returns boolean
local player owner = GetOwningPlayer(GetTriggerUnit())
if GetResearched() == UpToFrig then
call SetPlayerTechResearched(owner, HasFrig, 1)
call DisplayTextToPlayer(owner,0.,0.,"Mothership upgraded to frigate")
call Upgrade(MotherShip[GetPlayerId(owner)])
return false
elseif GetResearched() == UpToCruiz then
call SetPlayerTechResearched(owner, HasCruiz, 1)
call DisplayTextToPlayer(owner,0.,0.,"Mothership upgraded to cruiser")
call Upgrade(MotherShip[GetPlayerId(owner)])
return false
endif
set owner = null
return false
endfunction
private function init takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
local integer i = 0
set HashT = InitHashtable()
call SetVariables()
call AbilityPreload(ISMSMOD)
call RegisterSpellCastResponse(PICKMSMER,MsMer)
call RegisterSpellCastResponse(PICKMSMIL,MsMil)
call RegisterSpellCastResponse(PICKMSPIR,MsPir)
call RegisterSpellCastResponse(PICKMSPOL,MsPol)
call TriggerRegisterAnyUnitEventBJ(t1, EVENT_PLAYER_UNIT_RESEARCH_FINISH )
call TriggerAddCondition(t1, Condition(function UpgradeMainBody))
call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_TRAIN_FINISH )
call TriggerAddCondition(t2, Condition(function AddModule))
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library OrbSysTerrorist initializer init needs Table, TimerUtils, Resource,TextDisplay
globals
private constant real TIMEOUTMS = 0.05
private constant integer SLOT = 14
private constant string C = "The Motherhsip has to much buildings orbiting arround it."
constant integer ISTERROMSSAT = 'A013'
constant integer TERRORISTMS = 'H009'
unit array TerroristMs [9]
endglobals
private keyword s_OrbSysTerrorist
globals
private HandleTable TABLE
endglobals
private struct s_OrbSysTerrorist
private unit mothership = null
private timer ti = null
private unit array sat [SLOT]
private real array a [SLOT]
private real array d [SLOT]
private real angle = 0.
method destroy takes nothing returns nothing
local integer i = 0
if .ti != null then
call ReleaseTimer(.ti)
set .ti = null
endif
loop
exitwhen i > SLOT - 1
call KillUnit(.sat[i])
set .sat[i] = null
set i = i + 1
endloop
set .mothership = null
endmethod
method Update takes nothing returns nothing
local integer i = 0
local real x1 = GetUnitX(.mothership)
local real y1 = GetUnitY(.mothership)
local real x2 = 0.
local real y2 = 0.
if GetUnitState(.mothership, UNIT_STATE_LIFE) > 0 then
set .angle = .angle + 0.01
loop
exitwhen i > SLOT-1
if GetUnitState(.sat[i], UNIT_STATE_LIFE) > 0 then
set x2 = x1+.d[i]*Cos(.angle+.a[i]*bj_DEGTORAD)
set y2 = y1+.d[i]*Sin(.angle+.a[i]*bj_DEGTORAD)
if IsUnitType(.sat[i],UNIT_TYPE_TAUREN)== true then
call SetUnitX(.sat[i],x2)
call SetUnitY(.sat[i],y2 )
else
call SetUnitPosition(.sat[i],x2,y2)
endif
else
set .sat[i] = null
endif
set i = i + 1
endloop
else
call .destroy()
endif
endmethod
private static method RunUpdate takes nothing returns nothing
call thistype(GetTimerData(GetExpiredTimer())).Update()
endmethod
method preventBuilding takes unit sat returns nothing
local integer i = 0
local integer r1 = 0
local integer r2 = 0
local player owner = GetOwningPlayer(sat)
call RemoveUnit(sat)
loop
set i = i + 1
exitwhen i > CostMax
if GetUnitTypeId(sat)== CostUnitId[i] then
set r1 = CostGold[i]
set r2 = CostLumber[i]
endif
endloop
call DisplayTextToPlayer(owner, 0, 0, C)
call ErrorSound(owner)
call SetResource(owner,r1,r2)
set owner = null
endmethod
method linkSat takes unit sat returns nothing
local integer i = 0
local real x1 = GetUnitX(.mothership)
local real y1 = GetUnitY(.mothership)
local real x2 = 0.
local real y2 = 0.
//Refresh: dead sat are cancelled
loop
exitwhen i > SLOT-1
if GetUnitState(.sat[i], UNIT_STATE_LIFE) <= 0 then
set .sat[i] = null
endif
set i = i + 1
endloop
//Seting the new satellite
set i = 0
loop
exitwhen i > SLOT-1
if .sat[i] == null and i <= 13 then
set .sat[i] = sat
call SetUnitPathing(sat,false)
set x2 = x1+.d[i]*Cos(.a[i]*bj_DEGTORAD)
set y2 = y1+.d[i]*Sin(.a[i]*bj_DEGTORAD)
call SetUnitPosition(sat,x2,y2)
return
endif
set i = i + 1
endloop
call .preventBuilding(sat)
endmethod
method setProperties takes nothing returns nothing
local integer i = 0
loop
exitwhen i > SLOT
if i <=5 then
set .a[i]= 60.*i
set .d[i] = 100.
endif
if i >5 and i <= 13 then
set .a[i]= 45.*i
set .d[i] = 162.5
endif
set i = i + 1
endloop
set .ti = NewTimer()
call SetTimerData( .ti, this )
call TimerStart( .ti, TIMEOUTMS, true, function thistype.RunUpdate )
endmethod
method changeSat takes unit satbase, unit satnew returns nothing
local integer i = 0
local real x1 = GetUnitX(.mothership)
local real y1 = GetUnitY(.mothership)
local real x2 = 0.
local real y2 = 0.
call RemoveUnit(satbase)//remove the constructing unit
//Refresh: dead sat are cancelled
loop
exitwhen i > SLOT-1
if GetUnitState(.sat[i], UNIT_STATE_LIFE) <= 0 then
set .sat[i] = null
endif
set i = i + 1
endloop
//Seting the new satellite
set i = 0
loop
exitwhen i > SLOT-1
if .sat[i] == null and i <= 13 then
set .sat[i] = satnew
call SetUnitPathing(satnew,false)
set x2 = x1+.d[i]*Cos(.a[i]*bj_DEGTORAD)
set y2 = y1+.d[i]*Sin(.a[i]*bj_DEGTORAD)
call SetUnitPosition(satnew,x2,y2)
return
endif
set i = i + 1
endloop
endmethod
//Constructor
static method create takes unit mothership returns s_OrbSysTerrorist
local s_OrbSysTerrorist this = s_OrbSysTerrorist.allocate()
set this.mothership = mothership
return this
endmethod
endstruct
function OrbSysTerrorist takes unit mothership returns s_OrbSysTerrorist
if( mothership==null )then
return 0
endif
if( not TABLE.exists(mothership) )then
set TABLE[mothership] = s_OrbSysTerrorist.create(mothership)
endif
return s_OrbSysTerrorist(TABLE[mothership])
endfunction
private function AddSat takes nothing returns boolean
if IsUnitType(GetTrainedUnit(), UNIT_TYPE_MECHANICAL) == true and GetUnitTypeId(GetTriggerUnit()) == TERRORISTMS then
call OrbSysTerrorist(GetTriggerUnit()).linkSat(GetTrainedUnit())
endif
return false
endfunction
private function AddMotherShip takes nothing returns boolean
if GetUnitTypeId(GetTriggerUnit()) == TERRORISTMS then
call OrbSysTerrorist(GetTriggerUnit()).setProperties()
endif
return false
endfunction
private function init takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
set TABLE = HandleTable.create()
call TriggerRegisterAnyUnitEventBJ(t1, EVENT_PLAYER_UNIT_TRAIN_FINISH )
call TriggerAddCondition(t1, Condition(function AddSat))
call TriggerRegisterEnterRectSimple(t2, bj_mapInitialPlayableArea)
call TriggerAddCondition(t2, Condition( function AddMotherShip ) )
endfunction
endlibrary
//TESH.scrollpos=107
//TESH.alwaysfold=0
library TroopSys initializer init needs AbilityPreload, TextDisplay
globals
constant integer TROOPER = 'I006'
constant integer DROID = 'I004'
constant integer TANK = 'I005'
constant integer AIRCRAFT = 'I007'
private constant integer INV = 'A003'
private constant integer DEFTROOPER = 5
private constant integer DEFDROID = 20
private constant integer DEFTANK = 50
private constant integer DEFAIRCRAFT = 5
private constant integer ATTROOPER = 10
private constant integer ATDROID = 5
private constant integer ATTANK = 40
private constant integer ATAIRCRAFT = 80
private constant string FX = "Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl"
private constant integer DUMMYTROOPER = 'I002'
private constant integer DUMMYDROID = 'I003'
private constant integer DUMMYTANK = 'I001'
private constant integer DUMMYAIRCRAFT = 'I008'
endglobals
function SetTroop takes unit whichUnit,integer whichTroop,integer whichAmount returns nothing
local integer i = 0
local item carriedItem = null
loop
exitwhen i > 5
set carriedItem = UnitItemInSlot(whichUnit,i)
if GetItemTypeId(carriedItem)==TROOPER and whichTroop==TROOPER then
call SetItemCharges(carriedItem,whichAmount)
endif
if GetItemTypeId(carriedItem)==DROID and whichTroop==DROID then
call SetItemCharges(carriedItem,whichAmount)
endif
if GetItemTypeId(carriedItem)==TANK and whichTroop==TANK then
call SetItemCharges(carriedItem,whichAmount)
endif
if GetItemTypeId(carriedItem)==AIRCRAFT and whichTroop==AIRCRAFT then
call SetItemCharges(carriedItem,whichAmount)
endif
set i = i + 1
endloop
set carriedItem = null
endfunction
function GetTroop takes unit whichUnit, integer whichTroop returns integer
local integer i = 0
local item carriedItem = null
local integer carriedItemCharges = 0
loop
exitwhen i > 5
set carriedItem = UnitItemInSlot(whichUnit,i)
if GetItemTypeId(carriedItem)==TROOPER and whichTroop==TROOPER then
set carriedItemCharges = GetItemCharges(carriedItem)
set carriedItem = null
return carriedItemCharges
endif
if GetItemTypeId(carriedItem)==DROID and whichTroop==DROID then
set carriedItemCharges = GetItemCharges(carriedItem)
set carriedItem = null
return carriedItemCharges
endif
if GetItemTypeId(carriedItem)==TANK and whichTroop==TANK then
set carriedItemCharges = GetItemCharges(carriedItem)
set carriedItem = null
return carriedItemCharges
endif
if GetItemTypeId(carriedItem)==AIRCRAFT and whichTroop==AIRCRAFT then
set carriedItemCharges = GetItemCharges(carriedItem)
set carriedItem = null
return carriedItemCharges
endif
set i = i + 1
endloop
set carriedItem = null
return 0
endfunction
function GetAttackPower takes unit whichUnit returns integer
return GetTroop(whichUnit,TROOPER)*ATTROOPER+GetTroop(whichUnit,DROID)*ATDROID+GetTroop(whichUnit,TANK)*ATTANK+GetTroop(whichUnit,AIRCRAFT)*ATAIRCRAFT
endfunction
function GetDefencePower takes unit whichUnit returns integer
return GetTroop(whichUnit,TROOPER)*DEFTROOPER+GetTroop(whichUnit,DROID)*DEFDROID+GetTroop(whichUnit,TANK)*DEFTANK+GetTroop(whichUnit,AIRCRAFT)*DEFAIRCRAFT
endfunction
private function InitializeTroop takes nothing returns boolean
local unit entering = GetTriggerUnit()
local item carriedItem = null
if GetUnitAbilityLevel(entering,INV)>=1 and GetUnitState(entering,UNIT_STATE_LIFE)>0 then
if GetTroop(entering,TROOPER)==0 then
set carriedItem = CreateItem(TROOPER,0.,0.)
call UnitAddItem(entering,carriedItem)
call SetItemCharges(carriedItem, 2)
endif
if GetTroop(entering,DROID)==0 then
set carriedItem = CreateItem(DROID,0.,0.)
call UnitAddItem(entering,carriedItem)
call SetItemCharges(carriedItem, 0)
endif
if GetTroop(entering,TANK)==0 then
set carriedItem = CreateItem(TANK,0.,0.)
call UnitAddItem(entering,carriedItem)
call SetItemCharges(carriedItem, 0)
endif
endif
set entering = null
set carriedItem = null
return false
endfunction
private function BuyTroop takes nothing returns boolean
local unit buyer = GetBuyingUnit()
local player owner = GetOwningPlayer(buyer)
local item soldItem = GetSoldItem()
local integer soldItemId = GetItemTypeId(soldItem)
if soldItemId==DUMMYTROOPER or soldItemId==DUMMYTANK or soldItemId==DUMMYDROID then
call DestroyEffect(AddSpecialEffectTarget(FX,buyer,"origin"))
if soldItemId == DUMMYTROOPER then
call SetTroop(buyer,TROOPER,GetTroop(buyer,TROOPER)+1)
elseif soldItemId == DUMMYDROID then
call SetTroop(buyer,DROID,GetTroop(buyer,DROID)+1)
elseif soldItemId == DUMMYTANK then
call SetTroop(buyer,TANK,GetTroop(buyer,TANK)+1)
elseif soldItemId == DUMMYAIRCRAFT then
if Military[GetPlayerId(owner)]==true then
call SetTroop(buyer,AIRCRAFT,GetTroop(buyer,AIRCRAFT)+1)
else
call ErrorSound(owner)
call DisplayTextToPlayer(owner,0.,0.,"Only Militaries can build Aircrafts.")
endif
endif
endif
set owner = null
set buyer = null
set soldItem = null
return false
endfunction
private function init takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
call RemoveItem(CreateItem(TROOPER,0.,0.))
call RemoveItem(CreateItem(DROID,0.,0.))
call RemoveItem(CreateItem(TANK,0.,0.))
call TriggerRegisterEnterRectSimple(t1, bj_mapInitialPlayableArea)
call TriggerAddCondition( t1, Condition( function InitializeTroop ) )
call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_SELL_ITEM )
call TriggerAddCondition(t2, Condition(function BuyTroop))
endfunction
endlibrary
//TESH.scrollpos=223
//TESH.alwaysfold=0
library SetOptions initializer init needs SpellEvent, AbilityPreload
globals
constant integer CREEPSTRUE = 'A014'
constant integer CREEPSFALSE = 'A015'
integer VotePirate
constant integer BUILDERSHUT = 'h00M'
constant integer PICKMERCHANT = 'A03Q'
constant integer PICKMILITARY = 'A03S'
constant integer PICKPIRATE = 'A03R'
constant integer PICKTERRORIST = 'A03T'
constant integer PICKALIEN = 'A03U'
constant integer PICKRANDOM = 'A03V'
constant integer PICKMSMER = 'A03P'
constant integer PICKMSMIL = 'A03W'
constant integer PICKMSPIR = 'A03Z'
constant integer PICKMSPOL = 'A040'
endglobals
private function SetAlien takes integer id returns nothing
local integer i = 0
local unit mothership = null
set Alien[id] = true
set Merchant[id] = false
set Military[id] = false
set Pirate[id] = false
set Terrorist[id] = false
//Set handicap to 100%
call SetPlayerHandicap(Player(id),1.00)
//create an alien mothership and light shuttles
set mothership = CreateUnit(Player(id),'H01J',GetUnitX(FirstShip[id]),GetUnitY(FirstShip[id]),0.)
//Allows the unit to produce ships without being blocked by rallye point
call UnitRemoveAbility(mothership,'ARal')
loop
exitwhen i > 4
call CreateUnit(Player(id),'h00Q',GetUnitX(FirstShip[id]),GetUnitY(FirstShip[id]),0.)
set i = i + 1
endloop
call RemoveUnit(FirstShip[id])
set mothership = null
endfunction
private function SetMerchant takes integer id returns nothing
set Alien [id] = false
set Merchant[id] = true
set Military[id] = false
set Pirate[id] = false
set Terrorist[id] = false
call UnitAddAbility(FirstShip[id],PICKMSMER)
call UnitAddAbility(FirstShip[id],PICKMSPOL)
//Set handicap to 95%
call SetPlayerHandicap(Player(id),0.95)
//Merchant collect
call SetPlayerTechResearched(Player(id),'R00S',1)
//Disable Invasion Shuttle and Cruiser
call SetPlayerTechMaxAllowed(Player(id),'h01S',0)
call SetPlayerTechMaxAllowed(Player(id),'h01T',0)
//Disable Harrasser Pirate frigate
call SetPlayerTechMaxAllowed(Player(id),'h01H',0)
//Disable Cruiser: Pirate Marauder
call SetPlayerTechMaxAllowed(Player(id),'h00P',0)
//Disable Pirate Base
call SetPlayerTechMaxAllowed(Player(id),'o00I',0)
//Disable Frigate: StarkillerGunship
call SetPlayerTechMaxAllowed(Player(id),'h015',0)
//Disable MicroMissiles Thrower: Typhoon
call SetPlayerTechMaxAllowed(Player(id),'h018',0)
//Enable 1 MotherShip: Merchant Shuttle
call SetPlayerTechMaxAllowed(Player(id),'H02E',1)
//Disable MotherShip: Military Shuttle
call SetPlayerTechMaxAllowed(Player(id),'H02D',0)
//Disable MotherShip: Pirate Shuttle
call SetPlayerTechMaxAllowed(Player(id),'H02F',0)
//Enable 1 MotherShip: Polyvalent Shuttle
call SetPlayerTechMaxAllowed(Player(id),'H02C',1)
//Disable Biologic Weapons
call SetPlayerTechMaxAllowed(Player(id),'R00U',0)
//Disable Microblackhole generator MS mod
call SetPlayerTechMaxAllowed(Player(id),'E006',0)
//Disable MicroBlackHole
call SetPlayerAbilityAvailable(Player(id),'A01I',false)
//Disable Desyncrhonization
call SetPlayerAbilityAvailable(Player(id),'A036',false)
//Disable Telemetry
call SetPlayerAbilityAvailable(Player(id),'A026',false)
//Disable Set Up a ionic mine
call SetPlayerAbilityAvailable(Player(id),'A022',false)
//Disable Self Guided Mine
call SetPlayerAbilityAvailable(Player(id),'A02A',false)
//Disable Particle Shield
call SetPlayerAbilityAvailable(Player(id),'A024',false)
//Disable Aterburn
call SetPlayerAbilityAvailable(Player(id),'A027',false)
//Disable Derivation
call SetPlayerAbilityAvailable(Player(id),'A028',false)
//Set Fear to 2
call SetPlayerTechResearched(Player(id),'R00V',2)
endfunction
private function SetMilitary takes integer id returns nothing
set Alien [id] = false
set Merchant[id] = false
set Military[id] = true
set Pirate[id] = false
set Terrorist[id] = false
call UnitAddAbility(FirstShip[id],PICKMSMIL)
call UnitAddAbility(FirstShip[id],PICKMSPOL)
//Set Military Way to 1 (for Aircrafts)
call SetPlayerTechResearched(Player(id),'R00T',1)
//Set handicap to 110%
call SetPlayerHandicap(Player(id),1.10)
//Disable Cruiser: Pirate Marauder
call SetPlayerTechMaxAllowed(Player(id),'h00P',0)
//Disable Harrasser Pirate frigate
call SetPlayerTechMaxAllowed(Player(id),'h01H',0)
//Disable Spy Cruiser: Secret Agent
call SetPlayerTechMaxAllowed(Player(id),'h017',0)
//Disable Pirate Base
call SetPlayerTechMaxAllowed(Player(id),'o00I',0)
//Disable Radar Tower: Guardian
call SetPlayerTechMaxAllowed(Player(id),'h016',0)
//Disable MicroMissiles Thrower: Typhoon
call SetPlayerTechMaxAllowed(Player(id),'h018',0)
//Disable Merchant Cruiser: Miserly
call SetPlayerTechMaxAllowed(Player(id),'h01C',0)
//Disable 1 MotherShip: Merchant Shuttle
call SetPlayerTechMaxAllowed(Player(id),'H02E',0)
//Enable 1 MotherShip: Military Shuttle
call SetPlayerTechMaxAllowed(Player(id),'H02D',1)
//Disable MotherShip: Pirate Shuttle
call SetPlayerTechMaxAllowed(Player(id),'H02F',0)
//Enable 1 MotherShip: Polyvalent Shuttle
call SetPlayerTechMaxAllowed(Player(id),'H02C',1)
//Disable Desyncrhonization
call SetPlayerAbilityAvailable(Player(id),'A036',false)
//Disable Send Spy
call SetPlayerAbilityAvailable(Player(id),'A01Z',false)
//Disable Destructuration
call SetPlayerAbilityAvailable(Player(id),'A02B',false)
//Disable Alliance Income Bonus
call SetPlayerAbilityAvailable(Player(id),'A01Y',false)
//Disable Set Up a ionic mine
call SetPlayerAbilityAvailable(Player(id),'A022',false)
//Disable Aterburn
call SetPlayerAbilityAvailable(Player(id),'A027',false)
//Disable Nanite Saturation
call SetPlayerAbilityAvailable(Player(id),'A029',false)
//Disable Biologic Weapons
call SetPlayerTechResearched(Player(id),'R00U',0)
//Set Fear to 2
call SetPlayerTechResearched(Player(id),'R00V',2)
endfunction
private function SetPirate takes integer id returns nothing
set Alien [id] = false
set Merchant[id] = false
set Military[id] = false
set Pirate[id] = true
set Terrorist[id] = false
call UnitAddAbility(FirstShip[id],PICKMSPIR)
call UnitAddAbility(FirstShip[id],PICKMSPOL)
//Set handicap to 100%
call SetPlayerHandicap(Player(id),1.00)
//Enable pirate speed
call SetPlayerTechResearched(Player(id),'R00L',1)
//Enable 10 Pirate Bases
call SetPlayerTechMaxAllowed(Player(id),'o00I',10)
//Disable Invasion Shuttle and Cruiser
call SetPlayerTechMaxAllowed(Player(id),'h01S',0)
call SetPlayerTechMaxAllowed(Player(id),'h01T',0)
//Disable Frigate: StarkillerGunship
call SetPlayerTechMaxAllowed(Player(id),'h015',0)
//Disable Spy Cruiser: Secret Agent
call SetPlayerTechMaxAllowed(Player(id),'h017',0)
//Disable Radar Tower: Guardian
call SetPlayerTechMaxAllowed(Player(id),'h016',0)
//Disable MicroMissiles Thrower: Typhoon
call SetPlayerTechMaxAllowed(Player(id),'h018',0)
//Disable Merchant Cruiser: Miserly
call SetPlayerTechMaxAllowed(Player(id),'h01C',0)
//Disable MotherShip: Merchant Shuttle
call SetPlayerTechMaxAllowed(Player(id),'H02E',0)
//Disable MotherShip: Military Shuttle
call SetPlayerTechMaxAllowed(Player(id),'H02D',0)
//Disable MotherShip: Pirate Shuttle
call SetPlayerTechMaxAllowed(Player(id),'H02F',1)
//Enable 1 MotherShip: Polyvalent Shuttle
call SetPlayerTechMaxAllowed(Player(id),'H02C',1)
//Disable Microblackhole generator MS mod
call SetPlayerTechMaxAllowed(Player(id),'E006',0)
//Set Fear to 2
call SetPlayerTechResearched(Player(id),'R00V',2)
//Disable Colonize
call SetPlayerAbilityAvailable(Player(id),'A001',false )
//Disable Desyncrhonization
call SetPlayerAbilityAvailable(Player(id),'A036',false)
//Disable Destructuration
call SetPlayerAbilityAvailable(Player(id),'A02B',false)
//Disable Alliance Income Bonus
call SetPlayerAbilityAvailable(Player(id),'A01Y',false)
//Disable Send Spy
call SetPlayerAbilityAvailable(Player(id),'A01Z',false)
//Disable MicroBlackHole
call SetPlayerAbilityAvailable(Player(id),'A01I',false)
//Disable Telemetry
call SetPlayerAbilityAvailable(Player(id),'A026',false)
//Disable Self Guided Mine
call SetPlayerAbilityAvailable(Player(id),'A02A',false)
//Disable Particle Shield
call SetPlayerAbilityAvailable(Player(id),'A024',false)
//Disable Derivation
call SetPlayerAbilityAvailable(Player(id),'A028',false)
//Disable Nanite Saturation
call SetPlayerAbilityAvailable(Player(id),'A029',false)
//Disable Biologic Weapons
call SetPlayerTechResearched(Player(id),'R00U',0)
//Disable Improved Colonization
call SetPlayerTechResearched(Player(id),'R00G',0)
endfunction
private function SetTerrorist takes integer id returns nothing
set Alien [id] = false
set Merchant[id] = false
set Military[id] = false
set Pirate[id] = false
set Terrorist[id] = true
//Set handicap to 100%
call SetPlayerHandicap(Player(id),1.00)
//Disable Colonize
call SetPlayerAbilityAvailable(Player(id),'A001',false)
//Disable Instant Colonize
call SetPlayerAbilityAvailable(Player(id),'A007',false)
//Disable Improved Cargo Slot Research
call SetPlayerTechResearched(Player(id),'R00K',0)
//Disable Destructuration
call SetPlayerAbilityAvailable(Player(id),'A02B',false)
//Disable Alliance Income Bonus
call SetPlayerAbilityAvailable(Player(id),'A01Y',false)
//Disable Send Spy
call SetPlayerAbilityAvailable(Player(id),'A01Z',false)
//Disable MicroBlackHole
call SetPlayerAbilityAvailable(Player(id),'A01I',false)
//Disable Telemetry
call SetPlayerAbilityAvailable(Player(id),'A026',false)
//Disable Self Guided Mine
call SetPlayerAbilityAvailable(Player(id),'A02A',false)
//Disable Particle Shield
call SetPlayerAbilityAvailable(Player(id),'A024',false)
//Disable Derivation
call SetPlayerAbilityAvailable(Player(id),'A028',false)
//Disable Nanite Saturation
call SetPlayerAbilityAvailable(Player(id),'A029',false)
//Disable Destructuration
call SetPlayerAbilityAvailable(Player(id),'A02B',false)
//Disable Set Up a ionic mine
call SetPlayerAbilityAvailable(Player(id),'A022',false)
//Disable Aterburn
call SetPlayerAbilityAvailable(Player(id),'A027',false)
//Disable Invasion Shuttle and Cruiser
call SetPlayerTechMaxAllowed(Player(id),'h01S',0)
call SetPlayerTechMaxAllowed(Player(id),'h01T',0)
//Disable MicroMissile Thrower: Typhoon
call SetPlayerTechMaxAllowed(Player(id),'h018',0)
//Disable Merchant Cruiser: Miserly
call SetPlayerTechMaxAllowed(Player(id),'h01C',0)
//Enable 1 Research Facility Base(terrorist)
call SetPlayerTechMaxAllowed(Player(id),'h01K',1)
//Enable 1 Research Facility: Energy center
call SetPlayerTechMaxAllowed(Player(id),'h01A',1)
//Enable 1 Research Facility: Structure center
call SetPlayerTechMaxAllowed(Player(id),'h014',1)
//Enable 1 Research Facility: Weapon center
call SetPlayerTechMaxAllowed(Player(id),'h019',1)
//Enable 10 Turret Base (terrorist)
call SetPlayerTechMaxAllowed(Player(id),'h01Q',10)
//Enable 4 Torpedo Launcher System: Nova Thrower(terrorist)
call SetPlayerTechMaxAllowed(Player(id),'h01I',4)
//Enable 4 Ion Canon: Flash Caster(terrorist)
call SetPlayerTechMaxAllowed(Player(id),'h013',2)
//Enable 4 AA Turret: hurricane(terrorist)
call SetPlayerTechMaxAllowed(Player(id),'h00X',4)
//Enable 4 docks Mark I (terrorists)
call SetPlayerTechMaxAllowed(Player(id),'h01R',4)
//Enable 1 Terrorist Shipyard
call SetPlayerTechMaxAllowed(Player(id),'h01E',1)
set TerroristMs[id] = CreateUnit(Player(id),TERRORISTMS,GetUnitX(FirstShip[id]),GetUnitY(FirstShip[id]),0.)
//Allows the unit to produce ships without being blocked by rallye point
call UnitRemoveAbility(TerroristMs[id],'ARal')
//After MS created, ini its orbits
if Player(id) == GetLocalPlayer() then
call ClearSelection()
call SelectUnit(TerroristMs[id],true)
endif
call RemoveUnit(FirstShip[id])
endfunction
private function SetRandom takes integer id returns nothing
local integer random = GetRandomInt(1,4)
set random = GetRandomInt(0,4)
if random == 0 then
call DisplayTextToPlayer(Player(id), 0, 0, "You have randomed to be an Alien." )
call SetAlien(id)
elseif random == 1 then
call DisplayTextToPlayer(Player(id), 0, 0, "You have randomed to be a Merchant." )
call SetMerchant(id)
elseif random == 2 then
call DisplayTextToPlayer(Player(id), 0, 0, "You have randomed to be a Military." )
call SetMilitary(id)
elseif random == 3 then
call DisplayTextToPlayer(Player(id), 0, 0, "You have randomed to be a Pirate." )
call SetPirate(id)
elseif random == 4 then
call DisplayTextToPlayer(Player(id), 0, 0, "You have randomed to be a Terrorist." )
call SetTerrorist(id)
endif
endfunction
private function IniWay takes nothing returns nothing
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
local integer ownerId = GetPlayerId(owner)
call UnitRemoveAbility(SpellEvent.CastingUnit,PICKMERCHANT)
call UnitRemoveAbility(SpellEvent.CastingUnit,PICKMILITARY)
call UnitRemoveAbility(SpellEvent.CastingUnit,PICKPIRATE)
call UnitRemoveAbility(SpellEvent.CastingUnit,PICKTERRORIST)
call UnitRemoveAbility(SpellEvent.CastingUnit,PICKALIEN)
call UnitRemoveAbility(SpellEvent.CastingUnit,PICKRANDOM)
if GetLocalPlayer() == owner then
call PanCameraToTimed(GetUnitX(FirstShip[ownerId]),GetUnitY(FirstShip[ownerId]),0.)
endif
if SpellEvent.AbilityId == PICKMERCHANT then
call DisplayTextToPlayer(owner, 0, 0, "You have chosen to be a Merchant." )
call SetMerchant(ownerId)
elseif SpellEvent.AbilityId == PICKMILITARY then
call DisplayTextToPlayer(owner, 0, 0, "You have chosen to be a Military." )
call SetMilitary(ownerId)
elseif SpellEvent.AbilityId == PICKPIRATE then
call DisplayTextToPlayer(owner, 0, 0, "You have chosen to be a Pirate." )
call SetPirate(ownerId)
elseif SpellEvent.AbilityId == PICKTERRORIST then
call DisplayTextToPlayer(owner, 0, 0, "You have chosen to be a Terrorist." )
call SetTerrorist(ownerId)
elseif SpellEvent.AbilityId == PICKALIEN then
call DisplayTextToPlayer(owner, 0, 0, "You have chosen to be an Alien." )
call SetAlien(ownerId)
elseif SpellEvent.AbilityId == PICKRANDOM then
call SetRandom(ownerId)
endif
set owner = null
endfunction
private function SetCreeps takes nothing returns nothing
if SpellEvent.AbilityId == CREEPSTRUE then
set VotePirate = VotePirate + 1
endif
call UnitRemoveAbility(SpellEvent.CastingUnit,CREEPSTRUE)
call UnitRemoveAbility(SpellEvent.CastingUnit,CREEPSFALSE)
call UnitAddAbility(SpellEvent.CastingUnit,PICKMERCHANT)
call UnitAddAbility(SpellEvent.CastingUnit,PICKMILITARY)
call UnitAddAbility(SpellEvent.CastingUnit,PICKPIRATE)
call UnitAddAbility(SpellEvent.CastingUnit,PICKTERRORIST)
call UnitAddAbility(SpellEvent.CastingUnit,PICKALIEN)
call UnitAddAbility(SpellEvent.CastingUnit,PICKRANDOM)
endfunction
public function init takes nothing returns nothing
call AbilityPreload(PICKMSMER)
call AbilityPreload(PICKMSMIL)
call AbilityPreload(PICKMSPIR)
call AbilityPreload(PICKMSPOL)
call AbilityPreload(CREEPSTRUE)
call AbilityPreload(CREEPSFALSE)
call AbilityPreload(PICKMERCHANT)
call AbilityPreload(PICKMILITARY)
call AbilityPreload(PICKPIRATE)
call AbilityPreload(PICKTERRORIST)
call AbilityPreload(PICKALIEN)
call AbilityPreload(PICKRANDOM)
set VotePirate = 0
call RegisterSpellCastResponse(PICKMERCHANT,IniWay)
call RegisterSpellCastResponse(PICKMILITARY,IniWay)
call RegisterSpellCastResponse(PICKPIRATE,IniWay)
call RegisterSpellCastResponse(PICKTERRORIST,IniWay)
call RegisterSpellCastResponse(PICKALIEN,IniWay)
call RegisterSpellCastResponse(PICKRANDOM,IniWay)
call RegisterSpellCastResponse(CREEPSTRUE,SetCreeps)
call RegisterSpellCastResponse(CREEPSFALSE,SetCreeps)
endfunction
endlibrary
//TESH.scrollpos=4
//TESH.alwaysfold=0
library TradeSystem initializer init needs AbilityPreload,SpellEvent,TimerUtils,AutoIndex,Resource,BoardSystem,TextDisplay
globals
private constant string FXLOAD = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"
private constant string FXUNLOAD = "UI\\Feedback\\GoldCredit\\GoldCredit.mdl"
private constant integer TRADEABORTID = 'A00C' //ability which stops all trade operation for a cargo
private constant string TRADEABORTORDER = "flare"
private constant integer SELECTBUYER = 'A03H'
private constant integer SELLID = 'A04Q'
private constant string SELLORDER = "starfall"
private constant integer BUYID = 'A04R'
private constant string BUYORDER = "stasistrap"
private constant integer CARGOSHUTTLE = 'h00N'
private constant integer CARGOCRUISER = 'h01C'
private constant integer CARGOMOTHERSHIP3 = 'H02M'
private constant integer CARGOMOTHERSHIP2 = 'H02H'
private constant integer CARGOMOTHERSHIP1 = 'H02E'
private constant integer FREEPORT = 'h00O'
private constant integer PRODUCT = 'I000'
private constant integer CARGOSLOT = 'R00K'
private integer SPEEDBONUS = 'A020'
private constant string C1 = "|cff008040"
private constant string C2 = "|cff80FFFF"
private constant string C = " |r"
private constant string M1 = "Please select an allied FreePort"
private constant string M2 = "Only Merchants can trade with planets"
private constant string M3 = "You can not select your own freeport"
private constant integer CREATETRADEROAD = 'A03K'
constant integer GATE = 'OTsp'
private constant string G1 = "Please select an allied FreePort."
private constant string G2 = "Only Merchants can trade with planets."
private constant string G3 = "You need 500 iron to open a trade road."
private constant real INTERVAL = 250.
private constant integer MAXGATE = 100
private constant real GATESIZE = 0.5
endglobals
private struct s_GateSystem
destructable gate
unit targetFreeport = null
unit playerFreeport = null
method destroy takes nothing returns nothing
set .targetFreeport = null
set .playerFreeport = null
call KillDestructable(.gate)
set .gate = null
endmethod
endstruct
private struct s_RoadSystem
unit targetFreeport = null
unit playerFreeport = null
boolean road = false
static method operator [] takes unit u returns thistype
return thistype(GetUnitId(u))
endmethod
method destroy takes nothing returns nothing
set .targetFreeport = null
set .playerFreeport = null
set .road = false
endmethod
endstruct
private struct s_TradeSys
unit targetFreeport = null
unit playerFreeport = null
static method operator [] takes unit u returns thistype
return thistype(GetUnitId(u))
endmethod
method destroy takes nothing returns nothing
set .targetFreeport = null
set .playerFreeport = null
endmethod
endstruct
private function CheckRoadValidity takes nothing returns nothing
local timer t = GetExpiredTimer()
local s_GateSystem this = GetTimerData(t)
if GetUnitState(this.playerFreeport,UNIT_STATE_LIFE)<=0 or GetUnitState(this.targetFreeport,UNIT_STATE_LIFE)<=0 or this.targetFreeport == null or this.playerFreeport == null then
call ReleaseTimer(t)
call this.destroy()
endif
endfunction
private function RunGate takes unit playerFreeport, unit targetFreeport,destructable gate returns nothing
local timer t = NewTimer()
local s_GateSystem this = s_GateSystem.create()
set this.playerFreeport = playerFreeport
set this.targetFreeport = targetFreeport
set this.gate = gate
call SetTimerData(t, this)
call TimerStart (t, 5., true, function CheckRoadValidity )
endfunction
private function CheckSpeedBonus takes unit cargo, boolean add returns nothing
if add==true and GetUnitAbilityLevel(cargo,SPEEDBONUS)<=0 then
call UnitAddAbility(cargo,SPEEDBONUS)
elseif add==false and GetUnitAbilityLevel(cargo,SPEEDBONUS)>=1 then
call UnitRemoveAbility(cargo,SPEEDBONUS)
endif
endfunction
private function InitializeRoad takes unit playerFreeport,unit targetFreeport returns nothing
local s_RoadSystem this = s_RoadSystem[playerFreeport]
set this.targetFreeport = targetFreeport
set this.playerFreeport = playerFreeport
set this.road = true
endfunction
private function CreateTradeRoad takes nothing returns nothing
local integer i = 0
local unit roadCreator = SpellEvent.CastingUnit
local unit roadTarget = SpellEvent.TargetUnit
local player owner = GetOwningPlayer(roadCreator)
local real x1 = GetUnitX(roadCreator)
local real y1 = GetUnitY(roadCreator)
local real x2 = GetUnitX(roadTarget)
local real y2 = GetUnitY(roadTarget)
local real angle = Atan2((y2 -y1), (x2 - x1))
local real distance = SquareRoot((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
local destructable gate = null
if IsPlayerEnemy(owner,GetOwningPlayer(roadTarget))==false then
if GetUnitTypeId(roadTarget)==FREEPORT then
if GetPlayerState(owner,PLAYER_STATE_RESOURCE_LUMBER)>= 500 then
call SetPlayerState(owner, PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(owner,PLAYER_STATE_RESOURCE_LUMBER)-500)
call InitializeRoad(roadCreator,roadTarget)
call InitializeRoad(roadTarget,roadCreator)
loop
set i = i + 1
exitwhen i > distance/INTERVAL
set x2 = x1 + i*INTERVAL*Cos(angle)
set y2 = y1 + i*INTERVAL*Sin(angle)
set gate = CreateDestructable(GATE,x2,y2,angle*bj_RADTODEG,0.5,0)
call RunGate(roadCreator,roadTarget,gate)
endloop
set roadCreator = null
set roadTarget = null
set owner = null
set gate = null
return
else
call ErrorSound(owner)
call DisplayTextToPlayer(owner,0,0,G3)
endif
else
call ErrorSound(owner)
call DisplayTextToPlayer(owner,0,0,G1)
endif
else
call ErrorSound(owner)
call DisplayTextToPlayer(owner,0,0,G1)
endif
set roadCreator = null
set roadTarget = null
set owner = null
set gate = null
endfunction
private function IsFreeportAlive takes unit cargo returns boolean
local s_TradeSys this = s_TradeSys[cargo]
if GetUnitState(this.playerFreeport,UNIT_STATE_LIFE)>0 and GetUnitState(this.targetFreeport,UNIT_STATE_LIFE)>0 then
return true
else
call IssueImmediateOrder(cargo,TRADEABORTORDER)
return false
endif
endfunction
private function BuyOrder takes unit cargo returns nothing
local s_TradeSys this = s_TradeSys[cargo]
local s_RoadSystem dat = s_RoadSystem[this.playerFreeport]
if IsFreeportAlive(cargo)==true then
if dat.road==true then
call CheckSpeedBonus(cargo,true)
else
call CheckSpeedBonus(cargo,false)
endif
call IssueTargetOrder(cargo,BUYORDER,this.playerFreeport)
else
call IssueImmediateOrder(cargo,TRADEABORTORDER)
endif
endfunction
private function SellOrder takes unit cargo returns nothing
local s_TradeSys this = s_TradeSys[cargo]
local s_RoadSystem dat = s_RoadSystem[this.targetFreeport]
if IsFreeportAlive(cargo)==true then
if dat.road==true then
call CheckSpeedBonus(cargo,true)
else
call CheckSpeedBonus(cargo,false)
endif
call IssueTargetOrder(cargo,SELLORDER,this.targetFreeport)
else
call IssueImmediateOrder(cargo,TRADEABORTORDER)
endif
endfunction
private function GetProductAmount takes unit cargo returns integer
local integer i = 0
local item carriedItem = null
local integer carriedItemCharges = 0
loop
exitwhen i > 5
set carriedItem = UnitItemInSlot(cargo, i)
if GetItemTypeId(carriedItem) == PRODUCT then
set carriedItemCharges = GetItemCharges(carriedItem)
set carriedItem = null
return carriedItemCharges
endif
set i = i + 1
endloop
set carriedItem = null
return 0
endfunction
private function BuyOperation takes nothing returns nothing
local unit cargo = SpellEvent.CastingUnit
local s_TradeSys this = s_TradeSys[cargo]
local integer i = 0
local integer slotAmount = GetPlayerTechCount(GetOwningPlayer(cargo),CARGOSLOT,true)
local item carriedItem = null
loop
exitwhen i > 5
set carriedItem = UnitItemInSlot(cargo, i)
if GetItemTypeId(carriedItem) == PRODUCT and GetItemCharges(carriedItem)<=slotAmount then
call SetItemCharges(carriedItem,slotAmount)
endif
set i = i + 1
endloop
call DestroyEffect(AddSpecialEffectTarget(FXLOAD,cargo,"origin"))
call SellOrder(cargo)
set carriedItem = null
set cargo = null
endfunction
private function SellOperation takes nothing returns nothing
local unit cargo = SpellEvent.CastingUnit
local s_TradeSys this = s_TradeSys[cargo]
local integer productAmount = GetProductAmount(cargo)
local real dx = GetUnitX(this.playerFreeport)-GetUnitX(this.targetFreeport)
local real dy = GetUnitY(this.playerFreeport)-GetUnitY(this.targetFreeport)
local real distanteBetweenPorts = SquareRoot(dx*dx+dy*dy)
local integer gold = R2I(distanteBetweenPorts*0.05*0.05)*productAmount*2
local integer lumber = R2I(distanteBetweenPorts*0.02*0.05)*productAmount*2
local item carriedItem = null
local player owner = GetOwningPlayer(cargo)
local integer ownerId = GetPlayerId(owner)
local integer i = 0
loop
exitwhen i > 5
set carriedItem = UnitItemInSlot(cargo, i)
if GetItemTypeId(carriedItem) == PRODUCT then
call SetItemCharges(carriedItem,0)
endif
set i = i + 1
endloop
call DestroyEffect(AddSpecialEffectTarget(FXUNLOAD,cargo,"origin"))
//Bonus added if the owner of the cargo is a Merchant
if Merchant[GetPlayerId(owner)]== true then
set gold = R2I(gold*1.15)
set lumber = R2I(lumber*1.15)
endif
//Other bonuses for Merchant, if they have chosen a Merchant Mothership
if GetUnitTypeId(cargo)==CARGOCRUISER then
set gold = R2I(gold*10.)
set lumber = R2I(lumber*10.)
elseif GetUnitTypeId(cargo)==CARGOMOTHERSHIP1 then
set gold = R2I(gold*(5.+CountCargoMod(cargo)))
set lumber = R2I(lumber*(5.+CountCargoMod(cargo)))
elseif GetUnitTypeId(cargo)==CARGOMOTHERSHIP2 then
set gold = R2I(gold*(8.+CountCargoMod(cargo)))
set lumber = R2I(lumber*(8.+CountCargoMod(cargo)))
elseif GetUnitTypeId(cargo)==CARGOMOTHERSHIP3 then
set gold = R2I(gold*(13.+CountCargoMod(cargo)))
set lumber = R2I(lumber*(13.+CountCargoMod(cargo)))
endif
//Add the earned resources to the owner of the cargo, play a sound and display the earned resources
call SetResource(owner,gold,lumber)
call RunSoundOnUnit(SOUND_GOLD,cargo)
call Text(cargo,false,C1+I2S(gold)+C+" p, "+C2+I2S(lumber)+C+" i")
//If the owner of the cargo is a merchant, raises the experience points (rank system)
if Merchant[ownerId]==true then
call UpdateRank(owner,XP_TRADE)
endif
call BuyOrder(cargo)
set owner = null
set carriedItem = null
set cargo = null
endfunction
private function ReloadOrder takes unit cargo returns nothing
if GetProductAmount(cargo)>=1 then
call SellOrder(cargo)
else
call BuyOrder(cargo)
endif
endfunction
private function ReceiveOrder takes nothing returns boolean
local unit cargo = GetTriggerUnit()
local string s = OrderId2String(GetIssuedOrderId())
if s!=BUYORDER and s!=SELLORDER and s!=TRADEABORTORDER and GetUnitAbilityLevel(cargo,TRADEABORTID)>=1 then
call ReloadOrder(cargo)
endif
set cargo = null
return false
endfunction
private function ResetCargo takes unit cargo returns nothing
call UnitRemoveAbility(cargo,TRADEABORTID)
call UnitRemoveAbility(cargo,SELLID)
call UnitRemoveAbility(cargo,BUYID)
call UnitAddAbility(cargo,SELECTBUYER)
call CheckSpeedBonus(cargo,false)
endfunction
private function AbortTrade takes nothing returns nothing
local s_TradeSys this = s_TradeSys[SpellEvent.CastingUnit]
call this.destroy()
call ResetCargo(SpellEvent.CastingUnit)
endfunction
private function InitializeTrade takes unit cargo,unit targetFreeport returns nothing
local s_TradeSys this = s_TradeSys[cargo]
local player owner = GetOwningPlayer(cargo)
set this.targetFreeport = targetFreeport
set this.playerFreeport = Freeport[GetPlayerId(owner)]
call UnitRemoveAbility(cargo,SELECTBUYER)
call UnitAddAbility(cargo,TRADEABORTID)
call UnitAddAbility(cargo,SELLID)
call UnitAddAbility(cargo,BUYID)
call BuyOrder(cargo)
endfunction
private function SelectTradeTarget takes nothing returns nothing
local unit cargo = SpellEvent.CastingUnit
local unit buyer = SpellEvent.TargetUnit
local player owner = GetOwningPlayer(cargo)
local integer ownerId = GetPlayerId(owner)
if IsPlayerEnemy(owner,GetOwningPlayer(buyer))==false then
if GetUnitTypeId(buyer)==FREEPORT then
if buyer != Freeport[ownerId] then
call InitializeTrade(cargo,buyer)
else
call ErrorSound(owner)
call DisplayTextToPlayer(owner,0,0,M3)
endif
set cargo = null
set buyer = null
set owner = null
return
else
call ErrorSound(owner)
call DisplayTextToPlayer(owner,0,0,M1)
endif
else
call ErrorSound(owner)
call DisplayTextToPlayer(owner,0,0,M1)
endif
set cargo = null
set buyer = null
set owner = null
endfunction
private function AddProductsToEnteringShips takes nothing returns boolean
local unit entering = GetTriggerUnit()
local integer enteringId = GetUnitTypeId(entering)
local item product = null
if enteringId == CARGOSHUTTLE then
set product = CreateItem(PRODUCT,0.,0.)
call SetItemCharges(product,0)
call UnitAddItem(entering,product)
endif
set product = null
set entering = null
return false
endfunction
private function RemoveRoad takes unit freeport returns nothing
local s_RoadSystem this = s_RoadSystem[freeport]
call this.destroy()
endfunction
private function FreeportKilled takes nothing returns boolean
local unit killedUnit = GetTriggerUnit()
if GetUnitTypeId(killedUnit)==FREEPORT then
set Freeport[GetPlayerId(GetOwningPlayer(killedUnit))] = null
call RemoveRoad(killedUnit)
endif
set killedUnit = null
return false
endfunction
private function FreeportCreated takes nothing returns boolean
local unit constructed = GetConstructedStructure()
if GetUnitTypeId(constructed)==FREEPORT then
set Freeport[GetPlayerId(GetOwningPlayer(constructed))] = constructed
endif
set constructed = null
return false
endfunction
private function init takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
local trigger t3 = CreateTrigger()
local trigger t4 = CreateTrigger()
call AbilityPreload(CARGOSLOT)
call AbilityPreload(TRADEABORTID)
call AbilityPreload(SELECTBUYER)
call AbilityPreload(SELLID)
call AbilityPreload(BUYID)
call RemoveItem(CreateItem(PRODUCT,0.,0.))//antileak
call TriggerRegisterEnterRectSimple(t1, bj_mapInitialPlayableArea)//other events
call TriggerAddCondition( t1, Condition( function AddProductsToEnteringShips ) )
call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_CONSTRUCT_FINISH )
call TriggerAddCondition(t2, Condition(function FreeportCreated))
call TriggerRegisterAnyUnitEventBJ(t3, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
call TriggerRegisterAnyUnitEventBJ(t3, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
call TriggerRegisterAnyUnitEventBJ(t3, EVENT_PLAYER_UNIT_ISSUED_ORDER )
//call TriggerAddCondition(t3, Condition(function ReceiveOrder))
call TriggerRegisterAnyUnitEventBJ(t4, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition(t4, Condition(function FreeportKilled))
call RegisterSpellEffectResponse(SELECTBUYER,SelectTradeTarget)//when cargo use Select a Buyer skill
call RegisterSpellFinishResponse(TRADEABORTID,AbortTrade)//when cargo use Abort Trade skill
call RegisterSpellFinishResponse(SELLID,SellOperation)
call RegisterSpellFinishResponse(BUYID,BuyOperation)
call RegisterSpellCastResponse(CREATETRADEROAD,CreateTradeRoad) //gate system
endfunction
endlibrary
//TESH.scrollpos=7
//TESH.alwaysfold=0
library AICargo initializer init needs AutoIndex, GroupUtils
globals
private constant integer CARGO_ID = 'h00N'
private constant real AOE =3000.
private constant integer ASTEROID_ID = 'B000'
private constant integer MINE1_ID = 'n000' //équivelent de mine d'or
private constant integer MINE2_ID = 'n001'
private group MineGroup
private rect AsteroidRect = null
private real CargoX = 0.
private real CargoY = 0.
private real NearestDistance = 0.
private unit Mine = null
private destructable Asteroid = null
endglobals
private function CheckNearestAsteroid takes nothing returns nothing
local destructable enumDestructable = GetEnumDestructable()
local real x2 = GetDestructableX(enumDestructable)
local real y2 = GetDestructableY(enumDestructable)
local real dist = SquareRoot((CargoX-x2)*(CargoX-x2)+(CargoY-y2)*(CargoY-y2))
if GetDestructableTypeId(enumDestructable) ==ASTEROID_ID then
if (NearestDistance < 0) or (dist < NearestDistance) then
set Asteroid = enumDestructable
set NearestDistance = dist
endif
endif
set enumDestructable = null
endfunction
private function CheckIfAsteroid takes nothing returns boolean
return GetDestructableTypeId(GetFilterDestructable()) ==ASTEROID_ID
endfunction
private function FindNearestAsteroid takes real x, real y returns destructable
set NearestDistance = -1
set CargoX = x
set CargoY = y
set Asteroid = null
call MoveRectTo(AsteroidRect,CargoX,CargoY)
call EnumDestructablesInRect(AsteroidRect,Filter(function CheckIfAsteroid),function CheckNearestAsteroid)
return Asteroid
endfunction
private function CheckNearestMine takes nothing returns nothing
local unit enumUnit = GetEnumUnit()
local real x2 = GetUnitY(enumUnit)
local real y2 = GetUnitX(enumUnit)
local real dist = SquareRoot((CargoX-x2)*(CargoX-x2)+(CargoY-y2)*(CargoY-y2))
if GetUnitTypeId(enumUnit) == MINE1_ID or GetUnitTypeId(enumUnit) == MINE2_ID then
if NearestDistance < 0 or dist < NearestDistance then
set Mine = enumUnit
set NearestDistance = dist
endif
endif
set enumUnit = null
endfunction
private function CheckIfMine takes nothing returns boolean
return GetUnitTypeId(GetFilterUnit()) ==MINE1_ID or GetUnitTypeId(GetFilterUnit()) == MINE2_ID
endfunction
private function FindNearestMine takes real x, real y returns unit
set NearestDistance = -1
set CargoX = x
set CargoY = y
set Mine = null
set MineGroup = NewGroup()
call GroupEnumUnitsInRange(MineGroup, CargoX,CargoY, AOE, Filter(function CheckIfMine))
call ForGroup(MineGroup, function CheckNearestMine)
call ReleaseGroup(MineGroup)
return Mine
endfunction
private struct str
player owner
private static method createFilter takes unit u returns boolean
return GetPlayerController(GetOwningPlayer(u)) == MAP_CONTROL_USER and GetUnitTypeId(u)==CARGO_ID
endmethod
private method onCreate takes nothing returns nothing
local unit mine = null
local destructable asteroid = null
set .owner = GetOwningPlayer(me)
if GetRandomInt(0,100)<50 then
set mine = FindNearestMine(GetUnitX(me),GetUnitY(me))
if mine != null and not IsUnitType(mine,UNIT_TYPE_DEAD) then
call IssueTargetOrder(me,"smart",mine )
endif
else
set asteroid = FindNearestAsteroid(GetUnitX(me),GetUnitY(me))
if asteroid != null then
call IssueTargetOrder(me,"smart",asteroid )
endif
endif
endmethod
implement AutoCreate
private method onDestroy takes nothing returns nothing
set .owner = null
endmethod
implement AutoDestroy
endstruct
private function init takes nothing returns nothing
set AsteroidRect = Rect(0.-AOE,0.-AOE,0.+AOE,0.+AOE)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope pcv initializer init
globals
private constant real RADIUS = 1000.
endglobals
private function Spawn takes unit attacker, unit target returns nothing
local integer i = 0
local real x = GetUnitX(attacker)
local real y = GetUnitY(attacker)
local integer level = GetUnitLevel(target)
local integer spawnedUnitId = 0
local unit spawnedUnit = null
if CreepsPop <=10 then
if level > 0 and level <= 2 then
set spawnedUnitId = 'h000'
elseif level > 2 and level <= 3 then
set spawnedUnitId = 'h00C'
elseif level > 3 and level <= 5 then
set spawnedUnitId = 'h00G'
elseif level > 5 and level <= 7 then
set spawnedUnitId = 'h00I'
elseif level > 7 and level <= 10 then
set spawnedUnitId = 'h00K'
elseif level > 10 and level <= 14 then
set spawnedUnitId = 'h00A'
elseif level > 15 then
set spawnedUnitId = 'h00D'
endif
loop
exitwhen i > GetRandomInt(1,5)
set i = i + 1
set x = GetUnitX(DummyAttackerPirate) + GetRandomReal(-RADIUS,RADIUS)
set y = GetUnitY(DummyAttackerPirate) + GetRandomReal(-RADIUS,RADIUS)
set spawnedUnit = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE),spawnedUnitId,x,y,0.)
call IssueTargetOrder(spawnedUnit,"attack",target)
call UnitApplyTimedLife(spawnedUnit,'BTLF',60.)
endloop
endif
set spawnedUnit = null
endfunction
private function CheckAttacker takes nothing returns boolean
if GetAttacker()==DummyAttackerPirate then
call Spawn(GetAttacker(),GetTriggerUnit())
endif
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition(t, Condition(function CheckAttacker))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope UnitDeathUpStats initializer init
globals
private constant string COLORGOLD = "|c00FFFF00"
private constant string SGOLD = "gold"
endglobals
private function Conditions takes nothing returns boolean
local unit killer = GetKillingUnit()
local unit killedPirate = GetTriggerUnit()
local player owner = GetOwningPlayer(GetTriggerUnit())
local integer random = 0
if GetPlayerController(owner) == MAP_CONTROL_USER and GetOwningPlayer(killedPirate) == Player(PLAYER_NEUTRAL_AGGRESSIVE) then
set CreepsPop = CreepsPop - 1
set random = GetRandomInt(2*GetUnitLevel(killedPirate),5*GetUnitLevel(killedPirate))
call Text(killedPirate,false,"+"+COLORGOLD+I2S(random)+"|r "+SGOLD)
call SetResource(owner,random,0)
endif
set killer = null
set killedPirate = null
set owner = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition( t, Condition( function Conditions ) )
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope AddErre initializer init
private function Conditions takes nothing returns boolean
local unit entering = GetTriggerUnit()
local integer enteringId = GetUnitTypeId(entering)
if GetUnitAbilityLevel(entering,ERRE)<= 0 and GetOwningPlayer(entering)==Player(PLAYER_NEUTRAL_AGGRESSIVE) and IsUnitType(entering,UNIT_TYPE_MECHANICAL)==false and enteringId != 'o00K' and enteringId != 'n003' and enteringId != 'o00N' then
call UnitAddAbility(entering,ERRE)
endif
set entering = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterEnterRectSimple( t, bj_mapInitialPlayableArea )
call TriggerAddCondition( t, Condition( function Conditions ) )
endfunction
endscope
//TESH.scrollpos=3
//TESH.alwaysfold=0
scope CheckUnitsLevels initializer init
globals
integer array UnitLevel3 [12]
integer array UnitLevel5 [12]
integer array UnitLevel10 [12]
endglobals
private function Death takes nothing returns boolean
local unit whichUnit = GetTriggerUnit()
local integer level = GetUnitLevel(whichUnit)
local integer ownerId = GetPlayerId(GetOwningPlayer(whichUnit))
if GetOwningPlayer(whichUnit)!=Player(PLAYER_NEUTRAL_AGGRESSIVE) then
if level == 3 then
set UnitLevel3[ownerId]=UnitLevel3[ownerId] - 1
elseif level == 5 then
set UnitLevel5[ownerId]=UnitLevel5[ownerId] - 1
elseif level == 10 then
set UnitLevel10[ownerId]=UnitLevel10[ownerId] - 1
endif
endif
set whichUnit = null
return false
endfunction
private function Enter takes nothing returns boolean
local unit whichUnit = GetTriggerUnit()
local integer level = GetUnitLevel(whichUnit)
local integer ownerId = GetPlayerId(GetOwningPlayer(whichUnit))
if GetOwningPlayer(whichUnit)==Player(PLAYER_NEUTRAL_AGGRESSIVE) then
set CreepsPop = CreepsPop + 1
elseif GetOwningPlayer(whichUnit) == PLAYER_SLOT_STATE_PLAYING then
if level == 3 then
set UnitLevel3[ownerId]=UnitLevel3[ownerId] + 1
elseif level == 5 then
set UnitLevel5[ownerId]=UnitLevel5[ownerId] + 1
elseif level == 10 then
set UnitLevel10[ownerId]=UnitLevel10[ownerId] + 1
endif
endif
set whichUnit = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
local integer i = 0
loop
exitwhen i > MAXPLAYER
set UnitLevel3[i]=0
set UnitLevel5[i]=0
set UnitLevel10[i]=0
set i = i + 1
endloop
set CreepsPop = 0
call TriggerRegisterEnterRectSimple(t1, bj_mapInitialPlayableArea)
call TriggerAddCondition( t1, Condition( function Enter) )
call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition( t2, Condition( function Death) )
endfunction
endscope
//TESH.scrollpos=51
//TESH.alwaysfold=0
library PirateBaseSystem needs GroupFunction, TimerUtils, TextDisplay,Resource
globals
private constant integer IDPLAYER = PLAYER_NEUTRAL_AGGRESSIVE
private constant real WAIT = 210.
private constant integer BASE = 'o00I'
private constant integer TURRET = 'A01A'
private constant integer MINE = 'n001'
private constant integer SHIP1 = 'h002'
private constant integer SHIP2 = 'h011'
private constant integer SHIP3 = 'h012'
private constant integer CARGO = 'h00N'
private constant integer LSHU = 'h000'
private constant integer ASHU = 'h00C'
private constant integer RFRI = 'h00L'
private constant integer LCRU = 'h00A'
private constant integer NSHU = 'h00G'
private constant integer NFRI = 'h00I'
private constant real DIS = 250.
integer CreepsPop
timer PirateTimerWait
unit PirateBase
unit PirateMine
unit array PirateShipyard [3]
private trigger PirateFirstRun
private trigger PirateBaseDestruction
private trigger PirateTrain
endglobals
private function filter1 takes nothing returns boolean
return IsUnitType(GetFilterUnit(),UNIT_TYPE_ANCIENT)==true
endfunction
private function PirateBaseCreation takes nothing returns nothing
local integer i =0
local real x1 = GetRandomReal(GetRectMinX(bj_mapInitialPlayableArea),GetRectMaxX(bj_mapInitialPlayableArea))
local real y1 = GetRandomReal(GetRectMinY(bj_mapInitialPlayableArea),GetRectMaxY(bj_mapInitialPlayableArea))
local real x2 = 0.
local real y2 = 0.
call DisplayAll("Radar Officer", "Pirate base detected")
call SetResource(Player(IDPLAYER),50000,50000)
call SetPlayerState( Player(IDPLAYER), PLAYER_STATE_RESOURCE_FOOD_CAP, 50 )
set PirateBase = CreateUnit(Player(IDPLAYER), BASE,x1,y1, GetRandomReal(0.,360.))
call UnitAddAbility(PirateBase,TURRET)
call UnitAddAbility(PirateBase,TURRET)
set x2 = x1 + GetRandomReal(-DIS,DIS)
set y2 = y1 + GetRandomReal(-DIS,DIS)
set PirateMine = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),MINE,x2,y2, GetRandomReal(0.,360.))
call AddResourceAmount(PirateMine,99000 )
set x2 = x1 + GetRandomReal(-DIS,DIS)
set y2 = y1 + GetRandomReal(-DIS,DIS)
set PirateShipyard[0] = CreateUnit(Player(IDPLAYER), SHIP1,x2,y2, GetRandomReal(0.,360.))
set x2 = x1 + GetRandomReal(-DIS,DIS)
set y2 = y1 + GetRandomReal(-DIS,DIS)
set PirateShipyard[1] = CreateUnit(Player(IDPLAYER), SHIP2,x2,y2, GetRandomReal(0.,360.))
set x2 = x1 + GetRandomReal(-DIS,DIS)
set y2 = y1 + GetRandomReal(-DIS,DIS)
set PirateShipyard[2] = CreateUnit(Player(IDPLAYER), SHIP3,x2,y2, GetRandomReal(0.,360.))
loop
set i = i + 1
exitwhen i > 6
call IssueTargetOrder( CreateUnit(Player(IDPLAYER), CARGO,x1,y1, GetRandomReal(0.,360.)), "harvest", PirateMine)
endloop
endfunction
private function IniRunAgain takes nothing returns nothing
set PirateTimerWait = GetExpiredTimer()
call PirateBaseCreation()
endfunction
private function LoopRun takes nothing returns boolean
local player owner = GetOwningPlayer(GetTriggerUnit())
if GetTriggerUnit() == PirateBase then
set owner= GetOwningPlayer(GetKillingUnit())
call KillUnit(PirateMine)
call KillUnit(PirateShipyard[0])
call KillUnit(PirateShipyard[1])
call KillUnit(PirateShipyard[2])
call SetResource(owner,1000,500)
call DisplayAll("Game",PlayerColor[GetPlayerId(owner)] + GetPlayerName(owner) + "|r"+" has destroyed a Neutral Pirate Base.")
set PirateTimerWait = NewTimer()
call TimerStart(PirateTimerWait, 30., false, function IniRunAgain )
endif
set owner = null
return false
endfunction
private function TrainPirateUnits takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = 0
local real x1 = 0.
local real y1 = 0.
local real x2 = 0.
local real y2 = 0.
local real distance = 0.
local real angle = 0.
local unit spawnedUnit = null
loop
exitwhen i > MAXPLAYER
if CreepsPop <= 40 and GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
if UnitLevel3[i]>= 5 and GetUnitState(PirateShipyard[0], UNIT_STATE_LIFE) > 0 then
call IssueImmediateOrderById(PirateShipyard[0],NSHU)
call IssueImmediateOrderById(PirateShipyard[0],NSHU)
endif
if UnitLevel5[i]>= 5 and GetUnitState(PirateShipyard[1], UNIT_STATE_LIFE) > 0 then
call IssueImmediateOrderById(PirateShipyard[1],NFRI)
call IssueImmediateOrderById(PirateShipyard[1],NFRI)
endif
if UnitLevel10[i]>= 5 and GetUnitState(PirateShipyard[2], UNIT_STATE_LIFE) > 0 then
call IssueImmediateOrderById(PirateShipyard[2],LCRU)
call IssueImmediateOrderById(PirateShipyard[2],LCRU)
endif
call GroupEnumUnitsOfPlayer(ENUM_GROUP,Player(i),Condition(function filter1))
set x1 = GetUnitX(FirstOfGroup(ENUM_GROUP))
set y1 = GetUnitY(FirstOfGroup(ENUM_GROUP))
set angle = GetRandomReal(0.,360.)
set distance = GetRandomReal(600.,1500.)
set x2 = x1+distance*Cos(angle)
set y2 = y1+distance*Sin(angle)
set spawnedUnit = CreateUnit(Player(IDPLAYER),LSHU,x2,y2,angle)
call UnitApplyTimedLife(spawnedUnit,'BTLF',120.)
call UnitAddAbility(spawnedUnit, ERRE)
if UnitLevel10[i]>= 10 then
set angle = GetRandomReal(0.,360.)
set distance = GetRandomReal(600.,1500.)
set x2 = x1+distance*Cos(angle)
set y2 = y1+distance*Sin(angle)
set spawnedUnit = CreateUnit(Player(IDPLAYER),RFRI,x2,y2,angle)
call UnitApplyTimedLife(spawnedUnit,'BTLF',120.)
call UnitAddAbility(spawnedUnit, ERRE)
endif
endif
set i = i + 1
endloop
set spawnedUnit = null
endfunction
private function IniTrainPirateUnits takes nothing returns boolean
local timer t = NewTimer()
if CreepsEnabled==true then
call TimerStart (t, 121., true, function TrainPirateUnits )
endif
call ReleaseTimer(t)
return true
endfunction
private function FirstRun takes nothing returns boolean
call PirateBaseCreation()
return true
endfunction
function EnablePirateBase takes nothing returns nothing
set PirateFirstRun = CreateTrigger()
call TriggerRegisterTimerEvent( PirateFirstRun,WAIT,false)
call TriggerAddCondition(PirateFirstRun, Condition(function FirstRun))
set PirateBaseDestruction = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(PirateBaseDestruction,Player(IDPLAYER), EVENT_PLAYER_UNIT_DEATH,null )
call TriggerAddCondition(PirateBaseDestruction, Condition(function LoopRun))
set PirateTrain = CreateTrigger()
call TriggerRegisterTimerEvent( PirateTrain, WAIT,false)
call TriggerAddCondition(PirateTrain, Condition(function IniTrainPirateUnits))
endfunction
endlibrary
//TESH.scrollpos=18
//TESH.alwaysfold=0
scope AlienAttackOrder initializer init
globals
private constant integer SPELL = 'A04D'
private constant string FX = "Abilities\\Spells\\NightElf\\TrueshotAura\\TrueshotAura.mdl"
private constant real AOE = 300.
private constant real DUR = 2.
private unit Target
private player Owner
endglobals
private struct str
effect e = null
endstruct
private function Wait takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
call ReleaseTimer(t)
call DestroyEffect(dat.e)
call dat.destroy()
endfunction
private function AddEffect takes unit target returns nothing
local timer t = NewTimer()
local str dat = str.create()
set dat.e = AddSpecialEffectTarget(FX,target,"origin")
call SetTimerData(t, dat)
call TimerStart (t, DUR, false, function Wait )
endfunction
private function FilterAndOrder takes nothing returns boolean
if IsUnitAlly(GetFilterUnit(),Owner)==true and GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>0 then
call IssueTargetOrder(GetFilterUnit(),"attack",Target)
endif
return true
endfunction
private function Actions takes nothing returns nothing
local real x = GetUnitX(SpellEvent.CastingUnit)
local real y = GetUnitY(SpellEvent.CastingUnit)
call AddEffect(SpellEvent.TargetUnit)
set Target = SpellEvent.TargetUnit
set Owner = GetOwningPlayer(SpellEvent.CastingUnit)
call GroupEnumUnitsInRange(ENUM_GROUP,x,y,AOE,Filter(function FilterAndOrder))
endfunction
public function init takes nothing returns nothing
call RegisterSpellFinishResponse(SPELL,Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope AlienFollowOrder initializer init
globals
private constant integer SPELL = 'A04E'
private constant string FX = "Abilities\\Spells\\Orc\\CommandAura\\CommandAura.mdl"
private constant real AOE = 300.
private constant real DUR = 2.
private unit Caster
private player Owner
endglobals
private struct str
effect e = null
endstruct
private function Wait takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
call ReleaseTimer(t)
call DestroyEffect(dat.e)
call dat.destroy()
endfunction
private function AddEffect takes unit caster returns nothing
local timer t = NewTimer()
local str dat = str.create()
set dat.e = AddSpecialEffectTarget(FX,caster,"origin")
call SetTimerData(t, dat)
call TimerStart (t, DUR, false, function Wait )
endfunction
private function FilterAndOrder takes nothing returns boolean
if IsUnitAlly(GetFilterUnit(),Owner)==true and GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>0 then
call IssueTargetOrder(GetFilterUnit(),"move",Caster)
endif
return true
endfunction
private function Actions takes nothing returns nothing
local real x = GetUnitX(SpellEvent.CastingUnit)
local real y = GetUnitY(SpellEvent.CastingUnit)
call AddEffect(SpellEvent.CastingUnit)
set Caster = SpellEvent.CastingUnit
set Owner = GetOwningPlayer(SpellEvent.CastingUnit)
call GroupEnumUnitsInRange(ENUM_GROUP,x,y,AOE,Filter(function FilterAndOrder))
endfunction
public function init takes nothing returns nothing
call RegisterSpellFinishResponse(SPELL,Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope OrganicSupremacy initializer init
globals
private constant integer RESEARCH = 'R011'
private constant integer AMOUNT = 5 //food added
private constant integer TURRET = 'A04K'
endglobals
private function Conditions takes nothing returns boolean
local unit ship = GetTriggerUnit()
local player owner = GetOwningPlayer(ship)
local integer i = GetPlayerTechCount(owner,RESEARCH,true)
if GetResearched()==RESEARCH then
call SetPlayerState(owner,PLAYER_STATE_RESOURCE_FOOD_CAP,GetPlayerState(owner,PLAYER_STATE_RESOURCE_FOOD_CAP)+AMOUNT)
endif
if i==10 or i ==20 or i==30 or i==40 or i==50 or i==60 or i==70 or i==80 or i==90 or i== 100 then
call UnitAddAbility(ship,TURRET)
endif
set ship = null
set owner = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_RESEARCH_FINISH )
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=59
//TESH.alwaysfold=0
scope Assimilate initializer init
globals
private constant integer MAXALIENFOOD = 200
private constant string MESSAGE = "Congratulations,Planet Assimilated"
private constant integer SPELL = 'A04B'
private constant integer ASSIMILATING = 'A03L'
private constant integer DUR = 10
private constant integer AMOUNT = 16
private constant integer GOLD = 5000
private constant integer LUMBER = 1000
private constant string C1 = "|cff008040"
private constant string C2 = "|cff80FFFF"
private constant string C = " |r"
endglobals
private struct str
unit colonizer
unit planet
player owner
integer i
timer t
private static method createFilter takes unit u returns boolean
return GetUnitAbilityLevel(u,SPELL)>=1
endmethod
private method onCreate takes nothing returns nothing
set .colonizer = me
set .planet = null
set .t = null
set .owner = GetOwningPlayer(me)
endmethod
implement AutoCreate
private method onDestroy takes nothing returns nothing
set .colonizer = null
set .planet = null
set .t = null
set .owner = null
endmethod
implement AutoDestroy
endstruct
private function Update takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
local integer i = 0
if dat.i < DUR and not(IsUnitType(dat.colonizer,UNIT_TYPE_DEAD)) and not(IsUnitType(dat.planet,UNIT_TYPE_DEAD)) then
set dat.i = dat.i + 1
call Text(dat.colonizer,false,"Assimilate: "+I2S(DUR-dat.i)+" seconds left")
else
if dat.i >=DUR then
call DisplayTextToPlayer(dat.owner,0,0,MESSAGE)
call KillUnit(dat.planet)
loop
exitwhen i > AMOUNT-1
if GetPlayerState(dat.owner, PLAYER_STATE_RESOURCE_FOOD_USED)<MAXALIENFOOD then
call CreateUnit(dat.owner,'h00Q',GetUnitX(dat.planet),GetUnitY(dat.planet),0.)
endif
set i = i + 1
endloop
call SetResource(dat.owner,GOLD,LUMBER)
call Text(dat.colonizer,false,C1+I2S(GOLD)+C+" p, "+C2+I2S(LUMBER)+C+" i")
call UpdateRank(dat.owner,XP_ASSIMILATION)
endif
call UnitRemoveAbility(dat.colonizer,ASSIMILATING)
call ReleaseTimer(t)
endif
endfunction
private function RunColonization takes unit whichColonizer, unit whichPlanet returns nothing
local str dat = str[whichColonizer]
set dat.colonizer = whichColonizer
set dat.planet = whichPlanet
set dat.i = 0
call UnitAddAbility(dat.colonizer, ASSIMILATING)
call Text(dat.colonizer,false,"Assimilating")
set dat.t = NewTimer()
call SetTimerData(dat.t, dat)
call TimerStart (dat.t, 1., true, function Update )
endfunction
private function SpellEndCast takes nothing returns nothing
local str dat = str[SpellEvent.CastingUnit]
if not (SpellEvent.CastFinished) and dat.i < DUR then
call DisplayTextToPlayer(dat.owner, 0, 0, "Assimilation Aborted" )
call UnitRemoveAbility(dat.colonizer,ASSIMILATING)
call ReleaseTimer(dat.t)
endif
endfunction
private function SpellCast takes nothing returns nothing
call RunColonization(SpellEvent.CastingUnit,SpellEvent.TargetUnit)
endfunction
public function init takes nothing returns nothing
call AbilityPreload(ASSIMILATING)
call RegisterSpellCastResponse(SPELL,SpellCast)
call RegisterSpellEndCastResponse(SPELL,SpellEndCast)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope piratage2 initializer init
globals
private constant real COEFFMAX_GOLD = 0.75
private constant real COEFFMAX_LUMBER = 0.35
private constant integer IONID1 = 'A00K'
private constant integer IONID2 = 'A01F'
endglobals
private function Conditions takes nothing returns boolean
local unit pirate = GetAttacker()
local unit victim = GetTriggerUnit()
local player owner = GetOwningPlayer(pirate)
local integer ownerId = GetPlayerId(owner)
local integer randomgold = 0
local integer randomlumber = 0
if IsPlayerEnemy(owner,GetOwningPlayer(victim))==true and Pirate[ownerId]==true then
set randomgold = R2I(GetRandomReal(0.,COEFFMAX_GOLD)*GetUnitLevel(pirate)*GetUnitLevel(victim))
set randomlumber = R2I(GetRandomReal(0.,COEFFMAX_LUMBER)*GetUnitLevel(pirate)*GetUnitLevel(victim))
if GetUnitAbilityLevel(pirate,IONID1)>=1 or GetUnitAbilityLevel(pirate,IONID2)>=1 then
set randomgold = 4*randomgold
set randomlumber = 4*randomlumber
endif
call SetResource(owner,randomgold,randomlumber)
endif
set pirate = null
set victim = null
set owner = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=6
//TESH.alwaysfold=0
scope bioartillery initializer init
globals
private constant real TIMEOUT = 0.05
private constant integer DUR = 600 //DUR*TIMEOUT = duration in seconds and should be equal to LIFESPAN
private constant real LIFESPAN = 30. //security, the turret will be removed after 30 sec
private constant integer ID = 'h027'
private constant real DISTANCE = 45.00
private constant string FX = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"
private constant integer SPELL = 'A03G'
endglobals
private struct str
unit caster
unit turret
integer i
endstruct
private function MoveTurret takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
local real a = GetUnitFacing(dat.caster)
local real x = GetUnitX(dat.caster) -DISTANCE*Cos(a*bj_DEGTORAD)
local real y = GetUnitY(dat.caster) -DISTANCE*Sin(a*bj_DEGTORAD)
if dat.i <=DUR and dat.turret!=null and dat.caster!=null and GetUnitState(dat.turret, UNIT_STATE_LIFE) > 0 and GetUnitState(dat.caster, UNIT_STATE_LIFE) > 0 then
set dat.i = dat.i + 1
call SetUnitX(dat.turret,x)
call SetUnitY(dat.turret,y)
else
call RemoveUnit(dat.turret)
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
private function LinkTurret takes unit caster,unit turret returns nothing
local timer t = NewTimer()
local str dat = str.create()
set dat.caster = caster
set dat.turret = turret
set dat.i = 0
call SetTimerData(t, dat)
call TimerStart (t, TIMEOUT, true, function MoveTurret )
endfunction
private function Actions takes nothing returns nothing
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
local real x = GetUnitX(SpellEvent.CastingUnit)
local real y = GetUnitY(SpellEvent.CastingUnit)
local unit turret = CreateUnit(owner,ID,x,y,0.)
call DestroyEffect(AddSpecialEffectTarget(FX,turret,"origin"))
call UnitApplyTimedLife(turret,'BTLF',LIFESPAN)
call LinkTurret(SpellEvent.CastingUnit,turret)
set owner = null
set turret = null
endfunction
public function init takes nothing returns nothing
call RegisterSpellCastResponse(SPELL,Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope burndro initializer init
globals
constant integer BURNINGDRONE = 'n008'
private constant integer RESEARCH = 'R006'//improved physic weapons
private constant real DAMAGEBASE = 10. //base damage
private constant real DAMAGECOEFF = 1. //total dmg = base+coeff*level of research
private constant real AOE = 100.
endglobals
private function DealDamage takes unit drone returns nothing
local player owner = GetOwningPlayer(drone)
local real dmg = DAMAGEBASE+DAMAGECOEFF*GetPlayerTechCount(owner,RESEARCH, true)
if GetUnitTypeId(drone) == BURNINGDRONE then
call UnitDamageEnemies(drone,AOE,GetUnitX(drone),GetUnitY(drone),dmg)
endif
set owner = null
endfunction
private function CheckId takes nothing returns boolean
if GetUnitTypeId(GetTriggerUnit()) == BURNINGDRONE then
call DealDamage(GetTriggerUnit())
endif
return false
endfunction
private function KillDrone takes nothing returns boolean
local unit drone = GetAttacker()
if GetUnitTypeId(drone) == BURNINGDRONE then
call KillUnit(drone)
endif
set drone = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t1, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition(t1, Condition(function CheckId))
call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition(t2, Condition(function KillDrone))
endfunction
endscope
//TESH.scrollpos=1
//TESH.alwaysfold=0
scope Boarding initializer init
globals
private constant string FX = "UI\\Feedback\\GoldCredit\\GoldCredit.mdl"
private constant integer SPEED = 2
private constant integer SPELL = 'A016'
private constant real TIMEOUT = 0.05
endglobals
private function EndBoarding takes unit whichAttacker, unit whichTarget returns nothing
local player owner = GetOwningPlayer(whichAttacker)
if GetAttackPower(whichAttacker)- GetDefencePower(whichTarget) > 0 then
call SetUnitOwner(whichTarget,owner,false)
call DisplayTextToPlayer( owner, 0, 0, "Congratulations,Ship Captured" )
call SetTroop(whichAttacker,TROOPER,0)
call SetTroop(whichAttacker,DROID,0)
call SetTroop(whichAttacker,TANK,0)
call SetTroop(whichTarget,TROOPER,0)
call SetTroop(whichTarget,DROID,0)
call SetTroop(whichTarget,TANK,0)
call SetUnitOwner(whichTarget,owner,true)
else
call SetTroop(whichTarget,TROOPER,0)
call SetTroop(whichTarget,DROID,0)
call SetTroop(whichTarget,TANK,0)
call SetTroop(whichAttacker,TROOPER,0)
call SetTroop(whichAttacker,DROID,0)
call SetTroop(whichAttacker,TANK,0)
call DisplayTextToPlayer(owner, 0, 0, "Capture failed..." )
endif
set owner = null
endfunction
private struct str
unit target
unit caster
real angle
integer distance
lightning light
integer i
method destroy takes nothing returns nothing
set .target = null
set .caster = null
set .light = null
endmethod
endstruct
private function Update takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
local real x1 = GetUnitX(dat.caster)
local real y1 = GetUnitY(dat.caster)
local real z1 = GetUnitFlyHeight(dat.caster)+10.
local real x2 = GetUnitX(dat.target)
local real y2 = GetUnitY(dat.target)
local real z2 = GetUnitFlyHeight(dat.target)+10.
local real newX = x2 + SPEED*Cos(dat.angle)
local real newY = y2 + SPEED*Sin(dat.angle)
if dat.i < dat.distance and GetUnitState(dat.target, UNIT_STATE_LIFE) > 0 and GetUnitState(dat.caster, UNIT_STATE_LIFE) > 0 then
set dat.i = dat.i + 1
call SetUnitPosition(dat.target, newX, newY)
call IssueImmediateOrder(dat.caster,"stop")
call MoveLightningEx(dat.light,true,x1, y1, z1, x2, y2, z2 )
else
call UnitRemoveAbility( dat.caster, GARN)
call DestroyLightning(dat.light)
if dat.i >= dat.distance then
call EndBoarding(dat.caster,dat.target)
endif
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
private function RunBoard takes unit caster, unit target returns nothing
local timer t = NewTimer()
local str dat = str.create()
local real x1 = GetUnitX(caster)
local real y1 = GetUnitY(caster)
local real z1 = GetUnitFlyHeight(caster)
local real x2 = GetUnitX(target)
local real y2 = GetUnitY(target)
local real z2 = GetUnitFlyHeight(target)
set dat.target = target
set dat.caster = caster
set dat.angle = Atan2((y1-y2),(x1-x2))
set dat.distance =R2I(SquareRoot((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))/SPEED)
set dat.i = 0
call UnitAddAbility(dat.caster, GARN)
set dat.light = AddLightningEx("LEAS", true, x1, y1, z1, x2, y2, z2)
call SetTimerData(t, dat)
call TimerStart (t, TIMEOUT, true, function Update )
endfunction
private function CastBoard takes nothing returns nothing
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
if IsUnitType(SpellEvent.TargetUnit,UNIT_TYPE_HERO)==false and Alien[GetPlayerId(GetOwningPlayer(SpellEvent.TargetUnit))]==false then
if GetAttackPower(SpellEvent.CastingUnit)> 0 then
call RunBoard(SpellEvent.CastingUnit,SpellEvent.TargetUnit)
else
call UnitRemoveAbility(SpellEvent.CastingUnit,SPELL)
call UnitAddAbility(SpellEvent.CastingUnit,SPELL)
call DisplayTextToPlayer( owner,0,0,"You must load troops on your pirate cruiser! ")
call SetUnitState(SpellEvent.CastingUnit,UNIT_STATE_MANA,GetUnitState(SpellEvent.CastingUnit,UNIT_STATE_MANA)+100.)
call ErrorSound(owner)
call IssueImmediateOrder(SpellEvent.CastingUnit,"stop")
endif
else
call UnitRemoveAbility(SpellEvent.CastingUnit,SPELL)
call UnitAddAbility(SpellEvent.CastingUnit,SPELL)
call DisplayTextToPlayer( owner,0,0,"You can not abord Aliens or motherships" )
call SetUnitState(SpellEvent.CastingUnit,UNIT_STATE_MANA,GetUnitState(SpellEvent.CastingUnit,UNIT_STATE_MANA)+100.00)
call ErrorSound(owner)
call IssueImmediateOrder(SpellEvent.CastingUnit,"stop")
endif
set owner = null
endfunction
public function init takes nothing returns nothing
call RegisterSpellCastResponse(SPELL,CastBoard)
endfunction
endscope
//TESH.scrollpos=10
//TESH.alwaysfold=0
scope biotrap initializer init
globals
private constant integer DUR = 10
private constant integer ID = 'h026'
private constant string FX = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"
private constant integer SPELL = 'A031'
private constant real RADIUS = 150.
private constant integer COUNT = 6
private constant real ANGLE = 60.
private constant real TIMEOUT = 1.
endglobals
private struct str
unit turret
unit target
integer i
endstruct
private function ForceAttack takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
if dat.i <=DUR and GetUnitState(dat.target, UNIT_STATE_LIFE) > 0 then
set dat.i = dat.i + 1
call IssueTargetOrder(dat.turret,"attack",dat.target)
else
call RemoveUnit(dat.turret)
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
private function Link takes unit turret,unit target returns nothing
local timer t = NewTimer()
local str dat = str.create()
set dat.turret = turret
set dat.target = target
set dat.i = 0
call SetTimerData(t, dat)
call TimerStart (t, TIMEOUT, true, function ForceAttack )
endfunction
private function Actions takes nothing returns nothing
local integer i = 0
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
local unit dummy = null
local real x1 = GetUnitX(SpellEvent.TargetUnit)
local real y1 = GetUnitY(SpellEvent.TargetUnit)
local real x2 = 0.
local real y2 = 0.
loop
set i = i + 1
exitwhen i > COUNT
set x2 = x1 + RADIUS * Cos(ANGLE*i*bj_DEGTORAD)
set y2 = y1 + RADIUS * Sin(ANGLE*i*bj_DEGTORAD)
set dummy = CreateUnit(owner,ID,x2,y2,0.)
call DestroyEffect(AddSpecialEffect(FX,x2,y2))
call UnitApplyTimedLife(dummy,'BTLF',I2R(DUR))
call IssueTargetOrder(dummy,"attack",SpellEvent.TargetUnit)
call Link(dummy,SpellEvent.TargetUnit)
endloop
set owner = null
set dummy = null
endfunction
public function init takes nothing returns nothing
call RegisterSpellFinishResponse(SPELL,Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope camo initializer init
globals
private constant integer SPELL = 'A03A'
private constant integer DUMMYID = 'o00D'
private constant real DUR = 20.
endglobals
private function Actions takes nothing returns nothing
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
local real x = GetUnitX(SpellEvent.CastingUnit)
local real y = GetUnitY(SpellEvent.CastingUnit)
local unit dummy = CreateUnit(owner,DUMMYID, x,y,0.)
call UnitApplyTimedLife(dummy,'BTLF',DUR)
call IssuePointOrder(dummy,"cloudoffog",x,y)
set owner = null
set dummy = null
endfunction
public function init takes nothing returns nothing
call RegisterSpellCastResponse(SPELL,Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Cocoon initializer init
globals
private constant integer MAXALIENFOOD = 200
private constant integer SPELL = 'A04H'
private constant integer COCOONID = 'n00B'
private constant integer ALPHA = 'h00Q'
private constant integer AMOUNT = 4
endglobals
private function DeathCoon takes nothing returns boolean
local unit dying = GetTriggerUnit()
local player owner = GetOwningPlayer(dying)
local real x = GetUnitX(dying)
local real y = GetUnitY(dying)
local integer i = 0
if GetUnitTypeId(dying)==COCOONID then
loop
set i = i + 1
exitwhen i > AMOUNT
if GetPlayerState(owner, PLAYER_STATE_RESOURCE_FOOD_USED)<MAXALIENFOOD then
call CreateUnit(owner,ALPHA,x,y,GetRandomReal(0.,360.))
endif
endloop
endif
set dying = null
set owner = null
return false
endfunction
private function SpawnCoon takes nothing returns nothing
local real x = GetUnitX(SpellEvent.TargetUnit)
local real y = GetUnitY(SpellEvent.TargetUnit)
call CreateUnit(GetOwningPlayer(SpellEvent.CastingUnit),COCOONID,x,y,GetRandomReal(0.,360.))
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call RegisterSpellFinishResponse(SPELL,SpawnCoon)
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition(t, Condition(function DeathCoon))
endfunction
endscope
//TESH.scrollpos=48
//TESH.alwaysfold=0
scope Colonization initializer init
globals
private constant integer COLONIZING = 'A02C'
private constant integer SPELL = 'A001'
private constant string MESSAGE = "Congratulations,Planet Colonized"
endglobals
private struct str
unit colonizer
unit planet
integer i
integer dur
timer t
private static method createFilter takes unit u returns boolean
return GetUnitAbilityLevel(u,SPELL)>=1
endmethod
private method onCreate takes nothing returns nothing
set .colonizer = me
set .planet = null
set .t = null
endmethod
implement AutoCreate
private method onDestroy takes nothing returns nothing
set .colonizer = null
set .planet = null
set .t = null
endmethod
implement AutoDestroy
endstruct
private function Update takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
if dat.i < dat.dur and not(IsUnitType(dat.colonizer,UNIT_TYPE_DEAD)) and not(IsUnitType(dat.planet,UNIT_TYPE_DEAD)) then
set dat.i = dat.i + 1
call Text(dat.colonizer,false,"Colonisation:"+I2S(dat.dur-dat.i)+"seconds left")
else
if dat.i >=dat.dur then
call SetUnitOwner(dat.planet,GetOwningPlayer(dat.colonizer),false)
call KillUnit(dat.colonizer)
call DisplayTextToPlayer(GetOwningPlayer(dat.colonizer),0.,0.,MESSAGE)
endif
call UnitRemoveAbility(dat.colonizer,COLONIZING)
call ReleaseTimer(dat.t)
endif
endfunction
private function RunColonization takes unit whichColonizer, unit whichPlanet returns nothing
local str dat = str[whichColonizer]
set dat.colonizer = whichColonizer
set dat.planet = whichPlanet
set dat.i = 0
set dat.dur = R2I(120.-(10.*GetUnitAbilityLevel(dat.colonizer,SPELL)))
call UnitAddAbility(dat.colonizer, COLONIZING)
call Text(dat.colonizer,false,"colonizing")
set dat.t = NewTimer()
call SetTimerData(dat.t, dat)
call TimerStart (dat.t, 1., true, function Update )
endfunction
private function SpellCast takes nothing returns nothing
if GetOwningPlayer(SpellEvent.TargetUnit)==Player(PLAYER_NEUTRAL_PASSIVE) then
call RunColonization(SpellEvent.CastingUnit,SpellEvent.TargetUnit)
endif
endfunction
private function SpellEndCast takes nothing returns nothing
local str dat = str[SpellEvent.CastingUnit]
if not (SpellEvent.CastFinished) and dat.i < dat.dur then
call DisplayTextToPlayer( GetOwningPlayer(SpellEvent.CastingUnit), 0, 0, "Colonization Aborted" )
call UnitRemoveAbility(dat.colonizer,COLONIZING)
call ReleaseTimer(dat.t)
endif
endfunction
public function init takes nothing returns nothing
call AbilityPreload(COLONIZING)
call RegisterSpellCastResponse(SPELL,SpellCast)
call RegisterSpellEndCastResponse(SPELL,SpellEndCast)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope ColonizationInstant initializer init
globals
private constant real TIMEOUT = 1.
private constant integer SPELL = 'A007'
endglobals
private function Actions takes nothing returns nothing
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
local integer ownerId = GetPlayerId(owner)
if GetOwningPlayer(SpellEvent.TargetUnit)==Player(PLAYER_NEUTRAL_PASSIVE) then
call SetPlayerAbilityAvailable(owner,SPELL,false)
call SetUnitOwner(SpellEvent.TargetUnit,owner,false)
call DisplayTextToPlayer(owner, 0, 0, "Congratulations,Planet Colonized" )
endif
set owner = null
endfunction
public function init takes nothing returns nothing
call RegisterSpellFinishResponse(SPELL,Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope unitdeath initializer init
globals
private constant string FX = "fx_explosion_squished.mdx"
endglobals
private function Conditions takes nothing returns boolean
local integer i = 0
local unit dying = GetTriggerUnit()
local player owner = GetOwningPlayer(dying)
local integer ownerId = GetPlayerId(owner)
local real x = GetUnitX(dying)
local real y = GetUnitY(dying)
loop
exitwhen i > 5
call RemoveItem(UnitItemInSlot(dying,i))
set i = i + 1
endloop
if IsUnitType(dying,UNIT_TYPE_GIANT)==false and Alien[ownerId]==false then
call DestroyEffect(AddSpecialEffect(FX,x,y))
endif
set dying = null
set owner = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope terroism initializer init
private function Conditions takes nothing returns boolean
local unit terrorist = GetKillingUnit()
local unit victim = GetTriggerUnit()
local player owner = GetOwningPlayer(terrorist)
local integer ownerId = GetPlayerId(owner)
local integer randomgold = 0
local integer randomlumber = 0
if IsPlayerEnemy(owner,GetOwningPlayer(victim))==true and Terrorist[ownerId]==true then
set randomgold = R2I(GetRandomReal(5.00,10.00)*GetUnitLevel(terrorist)*GetUnitLevel(victim))
set randomlumber = R2I(GetRandomReal(5.00,10.00)*GetUnitLevel(terrorist)*GetUnitLevel(victim))
call SetResource(owner,randomgold,randomlumber)
call UpdateRank(owner,XP_DEATH)
endif
set terrorist = null
set victim = null
set owner = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=23
//TESH.alwaysfold=0
scope destructstat initializer init
globals
private constant real TIMEOUT = 1.00
private constant integer DUR = 20
private constant real AOE = 500.
private constant integer SPELL = 'A03F'
private constant integer BUFF = 'A025'
private constant integer DUMMYID = 'o014'
private constant integer DUMMYSPELL = 'A044'
private constant integer RESEARCH = 'R00U'
private player Owner = null
private unit Caster = null
endglobals
private function FilterEnemies takes nothing returns boolean
if IsUnitEnemy(GetFilterUnit(),Owner)==true and IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE)==false and IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD)==false then
call LightningLink(Caster,GetFilterUnit(), "DRAL", 1.,10.,10.)
endif
return true
endfunction
private struct str
unit caster
unit dummy
player owner
integer i
timer t
private static method createFilter takes unit u returns boolean
return GetUnitAbilityLevel(u,SPELL)>=1
endmethod
private method onCreate takes nothing returns nothing
set .caster = me
set .dummy = null
set .owner = GetOwningPlayer(me)
set .t = null
set .i = 0
endmethod
implement AutoCreate
private method onDestroy takes nothing returns nothing
if GetUnitAbilityLevel(.caster,BUFF)>=1 then
call UnitRemoveAbility(.caster,BUFF)
endif
set .caster = null
set .dummy = null
set .owner = null
set .t = null
set .i = 0
endmethod
implement AutoDestroy
endstruct
private function Check takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
local real x = GetUnitX(dat.caster)
local real y = GetUnitY(dat.caster)
if dat.i < DUR and GetUnitState(dat.caster, UNIT_STATE_LIFE) > 0 and GetUnitAbilityLevel(dat.caster,BUFF)>=1 then
set dat.i = dat.i + 1
//create the dummy for the damage
set dat.dummy = CreateUnit(dat.owner,DUMMYID,x,y,0.)
call SetUnitAbilityLevel(dat.dummy,DUMMYSPELL,GetPlayerTechCount(dat.owner, RESEARCH, true))
call IssuePointOrder(dat.dummy,"acidbomb",x,y)
call UnitApplyTimedLife(dat.dummy,'BTLF',1.)
//Link the units with the lightning effects
set Caster = dat.caster
set Owner = dat.owner
call GroupEnumUnitsInRange(ENUM_GROUP, x,y,AOE,Filter(function FilterEnemies))
else
call ReleaseTimer(t)
endif
endfunction
private function CastSpell takes nothing returns nothing
local str dat = str[SpellEvent.CastingUnit]
set dat.caster = SpellEvent.CastingUnit
set dat.owner = GetOwningPlayer(dat.caster)
set dat.i = 0
call UnitAddAbility(dat.caster,BUFF)
set dat.t = NewTimer()
call SetTimerData(dat.t, dat)
call TimerStart (dat.t, TIMEOUT, true, function Check )
endfunction
private function StopSpell takes nothing returns nothing
local str dat = str[SpellEvent.CastingUnit]
call ReleaseTimer(dat.t)
endfunction
public function init takes nothing returns nothing
call RegisterSpellCastResponse(SPELL,CastSpell)
call RegisterSpellEndCastResponse(SPELL,StopSpell)
endfunction
endscope
//TESH.scrollpos=73
//TESH.alwaysfold=0
scope destructuration initializer init
globals
private constant real TIMEOUT = 1.00 //duration of an interval
private constant integer DUR = 10 //number of intervals
private constant real AOE = 500.
private constant integer SPELL = 'A02B'
private constant integer BUFF = 'A01V' //to check if the caster is channelling the spell
private constant integer RESEARCH = 'R00B' //improved fusion nanites
private constant real DAMAGEBASE = 20 //base damage
private constant real DAMAGECOEFF = 10 //total damage = dmgbase+dmgcoeff*level of RESEARCH
private unit Caster = null
private player Owner = null
endglobals
private struct str
unit caster
unit target
integer i
real dmg
player owner
timer t
private static method createFilter takes unit u returns boolean
return GetUnitAbilityLevel(u,SPELL)>=1
endmethod
private method onCreate takes nothing returns nothing
set .caster = me
set .target = null
set .owner = GetOwningPlayer(me)
set .t = null
set .i = 0
set .dmg = 0.
endmethod
implement AutoCreate
private method onDestroy takes nothing returns nothing
if GetUnitAbilityLevel(.caster,BUFF)>=1 then
call UnitRemoveAbility(.caster,BUFF)
endif
set .caster = null
set .target = null
set .owner = null
set .t = null
set .i = 0
set .dmg = 0.
endmethod
implement AutoDestroy
endstruct
private function LoopDrain takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
if dat.i < DUR and GetUnitState(dat.target, UNIT_STATE_LIFE) > 0 and GetUnitState(dat.caster, UNIT_STATE_LIFE) > 0 and GetUnitAbilityLevel(dat.caster,BUFF)>=1 then
set dat.i = dat.i + 1
call UnitDamageTarget(dat.caster, dat.target,dat.dmg,false,false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
call SetUnitState(dat.caster,UNIT_STATE_LIFE,GetUnitState(dat.caster, UNIT_STATE_LIFE)+0.25*dat.dmg)
call SetResource(dat.owner,R2I(0.25*dat.dmg),R2I(0.25*dat.dmg))
else
call ReleaseTimer(t)
endif
endfunction
private function IniDrain takes unit caster,unit target returns nothing
local str dat = str[caster]
set dat.caster = caster
set dat.target = target
set dat.owner = GetOwningPlayer(dat.caster)
set dat.dmg = DAMAGEBASE+DAMAGECOEFF*GetPlayerTechCount(dat.owner, RESEARCH, true)
set dat.i = 0
set dat.t = NewTimer()
call SetTimerData(dat.t, dat)
call TimerStart (dat.t,TIMEOUT, true, function LoopDrain)
endfunction
private function FilterEnemies takes nothing returns boolean
if IsUnitEnemy(GetFilterUnit(),Owner)==true and IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE)==false and IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD)==false then
call LightningLink(Caster,GetFilterUnit(), "DRAL", 10.,10.,10.)
call IniDrain(Caster,GetFilterUnit())
endif
return true
endfunction
private function CastSpell takes nothing returns nothing
call UnitAddAbility(SpellEvent.CastingUnit,BUFF)
set Caster = SpellEvent.CastingUnit
set Owner = GetOwningPlayer(SpellEvent.CastingUnit)
call GroupEnumUnitsInRange(ENUM_GROUP,GetUnitX(Caster),GetUnitY(Caster),AOE,Condition(function FilterEnemies))
endfunction
private function StopSpell takes nothing returns nothing
local str dat = str[SpellEvent.CastingUnit]
call ReleaseTimer(dat.t)
endfunction
public function init takes nothing returns nothing
call RegisterSpellFinishResponse(SPELL,CastSpell)
call RegisterSpellEndCastResponse(SPELL,StopSpell)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope summonfighter initializer init
globals
private constant string FX = "Abilities\\Spells\\Demon\\DarkPortal\\DarkPortalTarget.mdl"
endglobals
private function Conditions takes nothing returns boolean
local unit caster = GetSummoningUnit()
local unit drone = GetSummonedUnit()
local integer droneId = GetUnitTypeId(drone)
if GetUnitTypeId(caster) == 'n005' and (droneId == 'h01F' or droneId == 'h01G') then
call DestroyEffect(AddSpecialEffectTarget(FX,drone,"origin"))
call IndieSummon_SetMaster(drone,caster)
endif
set caster = null
set drone = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SUMMON )
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope invisibilite initializer init
globals
private constant integer INVIS = 'Apiv'
private constant integer SPELL = 'A017'
private constant real DUR = 60.
endglobals
private struct str
unit caster
endstruct
private function Wait takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
call UnitRemoveAbility(dat.caster,INVIS)
call ReleaseTimer(t)
call dat.destroy()
endfunction
private function Actions takes nothing returns nothing
local timer t = NewTimer()
local str dat = str.create()
set dat.caster = SpellEvent.CastingUnit
call UnitAddAbility(dat.caster,INVIS)
call SetTimerData(t, dat)
call TimerStart (t, DUR, false, function Wait )
endfunction
public function init takes nothing returns nothing
call AbilityPreload(INVIS)
call RegisterSpellFinishResponse(SPELL,Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope SpellHyperspace initializer onInit // requires AutoIndex,SpellEvent
globals
private constant integer HYP_SPELL = 'A000' //basic spell
private constant integer PORTAL_ID = 'OTsp'
private constant real DISTANCE = 200.
endglobals
private struct str
destructable portal_1
destructable portal_2
private static method createFilter takes unit u returns boolean
return GetUnitAbilityLevel(u,HYP_SPELL)>=1
endmethod
private method onCreate takes nothing returns nothing
set .portal_1 = null
set .portal_2 = null
endmethod
implement AutoCreate
private method onDestroy takes nothing returns nothing
set .portal_1 = null
set .portal_2 = null
endmethod
implement AutoDestroy
endstruct
private function PolarOffsetX takes real x,real dist,real rad returns real
return x + dist*Cos(rad)
endfunction
private function PolarOffsetY takes real x,real dist,real rad returns real
return x + dist*Sin(rad)
endfunction
private function SpellEffect takes nothing returns nothing
local str dat = str[SpellEvent.CastingUnit] // instance de struct réservée pour l'unit
local real x = GetUnitX(SpellEvent.CastingUnit)
local real y = GetUnitY(SpellEvent.CastingUnit)
local real angle = Atan2(y-SpellEvent.TargetY,x-SpellEvent.TargetX)
set dat.portal_1 = CreateDestructable(PORTAL_ID,PolarOffsetX(x,-DISTANCE,angle),PolarOffsetY(y,-DISTANCE,angle),angle*bj_RADTODEG,0.5,0)
set dat.portal_2 = CreateDestructable(PORTAL_ID,PolarOffsetX(SpellEvent.TargetX,DISTANCE,angle),PolarOffsetY(SpellEvent.TargetY,DISTANCE,angle),angle*bj_RADTODEG,0.5,0)
call SetDestructableAnimation(dat.portal_1,"birth")
call SetDestructableAnimation(dat.portal_2,"birth")
endfunction
private function SpellEndCast takes nothing returns nothing
local str dat = str[SpellEvent.CastingUnit]
if not (SpellEvent.CastFinished) then // le spell a été interrompu
call KillDestructable(dat.portal_1)
call KillDestructable(dat.portal_2)
endif
endfunction
private function SpellFinish takes nothing returns nothing
local str dat = str[SpellEvent.CastingUnit]
call SetUnitX(SpellEvent.CastingUnit,SpellEvent.TargetX)
call SetUnitY(SpellEvent.CastingUnit,SpellEvent.TargetY)
call SetUnitState(SpellEvent.CastingUnit,UNIT_STATE_LIFE,GetUnitState(SpellEvent.CastingUnit,UNIT_STATE_LIFE)-GetRandomReal(0.,0.20)*GetUnitState(SpellEvent.CastingUnit,UNIT_STATE_MAX_LIFE))
call KillDestructable(dat.portal_1)
call KillDestructable(dat.portal_2)
endfunction
private function onInit takes nothing returns nothing
call RegisterSpellEffectResponse(HYP_SPELL,SpellEffect) // effet du spell (mana retiré et cooldown activé)
call RegisterSpellFinishResponse(HYP_SPELL,SpellFinish) // spell achevé correctement
call RegisterSpellEndCastResponse(HYP_SPELL,SpellEndCast) // spell interrompu avant la fin (ou juste aprés l'event "finish")
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope plinvasion initializer init
globals
private constant integer ID ='h025'
private constant string FX = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"
constant integer INVADING = 'A041'
private constant integer SPELL = 'A010'
integer SOUND_ALARM
endglobals
private function End takes unit whichAttacker, unit whichTarget returns nothing
local player owner = GetOwningPlayer(whichAttacker)
local integer ownerId = GetPlayerId(owner)
if GetAttackPower(whichAttacker)- GetDefencePower(whichTarget) > 0 then
call SetUnitOwner(whichTarget,owner,false)
call DisplayTextToPlayer( owner, 0, 0, "Congratulations,Invasion is a success" )
call SetTroop(whichAttacker,TROOPER,0)
call SetTroop(whichAttacker,DROID,0)
call SetTroop(whichAttacker,TANK,0)
call SetTroop(whichTarget,TROOPER,0)
call SetTroop(whichTarget,DROID,0)
call SetTroop(whichTarget,TANK,0)
call SetUnitOwner(whichTarget,owner,true)
if Military[ownerId]==true then
call UpdateRank(owner,XP_INVASION)
endif
else
call SetTroop(whichTarget,TROOPER,0)
call SetTroop(whichTarget,DROID,0)
call SetTroop(whichTarget,TANK,0)
call SetTroop(whichAttacker,TROOPER,0)
call SetTroop(whichAttacker,DROID,0)
call SetTroop(whichAttacker,TANK,0)
call DisplayTextToPlayer(owner, 0, 0, "Invasion failed..." )
endif
set owner = null
endfunction
private struct str
unit invader
unit planet
unit dummy
integer i
integer dur
player owner
timer t
private static method createFilter takes unit u returns boolean
return GetUnitAbilityLevel(u,SPELL)>=1
endmethod
private method onCreate takes nothing returns nothing
set .invader = null
set .planet = null
set .dummy = null
set .owner = null
set .t = null
endmethod
implement AutoCreate
private method onDestroy takes nothing returns nothing
set .invader = null
set .planet = null
set .dummy = null
set .owner = null
set .t = null
endmethod
implement AutoDestroy
endstruct
private function Action takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
local real x1 = GetUnitX(dat.invader)
local real y1 = GetUnitY(dat.invader)
local real x2 = GetUnitX(dat.planet)
local real y2 = GetUnitY(dat.planet)
if dat.i < dat.dur and not (IsUnitType(dat.invader,UNIT_TYPE_DEAD)) and not (IsUnitType(dat.planet,UNIT_TYPE_DEAD)) then
set dat.i = dat.i + 1
set dat.dummy = CreateUnit(dat.owner,ID,x1,y1,GetUnitFacing(dat.invader))
call UnitApplyTimedLife(dat.dummy,'BTLF',4.00)
call DestroyEffect(AddSpecialEffectTarget(FX,dat.dummy,"origin"))
call IssuePointOrder(dat.dummy,"move",x2,y2)
call Text(dat.invader,false,"Invasion:"+I2S(dat.dur-dat.i)+"seconds left")
else
if dat.i >=dat.dur then
call End(dat.invader,dat.planet)
endif
call UnitRemoveAbility(dat.invader,INVADING)
call SetUnitPathing(dat.invader,true)
call ReleaseTimer(t)
endif
endfunction
private function RunInvasion takes unit invader, unit planet returns nothing
local str dat = str[invader]
set dat.invader = invader
set dat.planet = planet
set dat.i = 0
set dat.owner = GetOwningPlayer(dat.invader)
set dat.dur = 30
call UnitAddAbility(dat.invader,INVADING)
call Text(dat.invader,false,"Starting Invasion")
call RunSoundForPlayer(SOUND_ALARM,GetOwningPlayer(dat.planet))
call DisplayTextToPlayer(GetOwningPlayer(dat.planet),0.,0.,"A planet is under invasion!")
set dat.t = NewTimer()
call SetTimerData(dat.t, dat)
call TimerStart (dat.t, 1., true, function Action )
endfunction
private function SpellCast takes nothing returns nothing
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
if GetAttackPower(SpellEvent.CastingUnit)> 0 and GetOwningPlayer(SpellEvent.TargetUnit)!=Player(PLAYER_NEUTRAL_PASSIVE) then
call RunInvasion (SpellEvent.CastingUnit, SpellEvent.TargetUnit)
elseif GetAttackPower(SpellEvent.CastingUnit)<= 0 and GetOwningPlayer(SpellEvent.TargetUnit)!=Player(PLAYER_NEUTRAL_PASSIVE) then
call UnitRemoveAbility(SpellEvent.CastingUnit,SPELL)
call UnitAddAbility(SpellEvent.CastingUnit,SPELL)
call DisplayTextToPlayer(owner, 0, 0, "You need to load troops on your invasion ship" )
call SetUnitState(SpellEvent.CastingUnit,UNIT_STATE_MANA,GetUnitState(SpellEvent.CastingUnit,UNIT_STATE_MANA)+200.)
call ErrorSound(owner)
call IssueImmediateOrder(SpellEvent.CastingUnit,"stop")
endif
set owner = null
endfunction
private function SpellEndCast takes nothing returns nothing
local str dat = str[SpellEvent.CastingUnit]
if not(SpellEvent.CastFinished) and dat.i < dat.dur then
call DisplayTextToPlayer( GetOwningPlayer(SpellEvent.CastingUnit), 0, 0, "Invasion Aborted" )
call UnitRemoveAbility(dat.invader,INVADING)
call ReleaseTimer(dat.t)
endif
endfunction
public function init takes nothing returns nothing
call AbilityPreload(INVADING)
set SOUND_ALARM = DefineSound("Alarm.mp3", 1463, false, false)
call RegisterSpellCastResponse(SPELL,SpellCast)
call RegisterSpellEndCastResponse(SPELL,SpellEndCast)
endfunction
endscope
//TESH.scrollpos=21
//TESH.alwaysfold=0
scope IonsWeapons initializer init
globals
//Inonic Mine
private constant string FX_MINE = "war3mapImported\\fx_stomp_squished.mdx"
private constant integer DUMMYID = 'o00N'
private constant integer MINE = 'n006'
//Ion Weapons
private constant string FX = "war3mapImported\\fx_ion_squished.mdx"
private constant integer IONID1 = 'A00K'
private constant integer IONID2 = 'A01F'
private constant integer CHANCEBASE = 15
private constant integer CHANCECOEFF = 7
private constant integer RESEARCH = 'R007'
//Ion Fx
private constant real FX_TIMEOUT = 0.25
private constant real FX_AOE = 75.
private constant integer FX_COUNT = 5
//Ionic Mine Wall
private constant integer IMW_DUR = 20
private constant integer IMW_SPELL = 'A02Z'
private constant real IMW_TIMEOUT = 0.5
endglobals
private struct s_Ion
unit ship
integer i
real x
real y
endstruct
private function CreateFx takes nothing returns nothing
local timer t = GetExpiredTimer()
local s_Ion dat = GetTimerData(t)
local real x = dat.x+GetRandomReal(-FX_AOE,FX_AOE)
local real y = dat.y+GetRandomReal(-FX_AOE,FX_AOE)
if dat.i < FX_COUNT and GetUnitState(dat.ship, UNIT_STATE_LIFE) > 0then
set dat.i = dat.i + 1
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Orc\\LightningShield\\LightningShieldBuff.mdl",x,y))
else
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
private function IonAddFx takes unit whichUnit returns nothing
local timer t = NewTimer()
local s_Ion dat = s_Ion.create()
set dat.ship = whichUnit
set dat.x = GetUnitX(dat.ship)
set dat.y = GetUnitY(dat.ship)
set dat.i = 0
call SetTimerData(t, dat)
call TimerStart (t, FX_TIMEOUT, true, function CreateFx )
endfunction
private struct s_MineWall
unit caster
player owner
integer i
method destroy takes nothing returns nothing
set .caster = null
set .owner = null
endmethod
endstruct
private function MineWallSpawnMine takes nothing returns nothing
local timer t = GetExpiredTimer()
local s_MineWall dat = GetTimerData(t)
local real x = GetUnitX(dat.caster)
local real y = GetUnitY(dat.caster)
if dat.i < IMW_DUR and GetUnitState(dat.caster, UNIT_STATE_LIFE) > 0 then
set dat.i = dat.i + 1
call CreateUnit(dat.owner,MINE,x,y,0.)
else
call SetUnitPathing(dat.caster,true)
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
private function CastIonicMineWall takes nothing returns nothing
local timer t = NewTimer()
local s_MineWall dat = s_MineWall.create()
set dat.caster = SpellEvent.CastingUnit
set dat.i = 0
set dat.owner = GetOwningPlayer(dat.caster)
call SetUnitPathing(dat.caster,false)
call SetTimerData(t, dat)
call TimerStart (t,IMW_TIMEOUT,true, function MineWallSpawnMine)
endfunction
private function MineDeath takes unit mine returns nothing
local real x = GetUnitX(mine)
local real y = GetUnitY(mine)
local unit dummy = CreateUnit(GetOwningPlayer(mine),DUMMYID,x,y,0.)
call UnitApplyTimedLife(dummy,'BTLF',1.5)
call IssueImmediateOrder(dummy,"stomp")
call DestroyEffect(AddSpecialEffect(FX_MINE,x,y))
call IonAddFx(dummy)
set dummy = null
endfunction
private function CheckMineId takes nothing returns boolean
if GetUnitTypeId(GetTriggerUnit()) == MINE then
call MineDeath(GetTriggerUnit())
endif
return false
endfunction
private function IonDealAttack takes unit attacker, unit target returns nothing
local integer i = GetRandomInt(0,100)
local integer chance = GetRandomInt(0,100)
local player owner = GetOwningPlayer(attacker)
local integer chancereq = CHANCEBASE+CHANCECOEFF*GetPlayerTechCount(owner,RESEARCH,true)
local real x = GetUnitX(target)
local real y = GetUnitY(target)
local unit dummy = null
if chance<=chancereq then
set dummy = CreateUnit(owner,'o00F',x,y,0.) //Ion Buff on target
call DestroyEffect(AddSpecialEffect(FX,x,y))
call UnitApplyTimedLife(dummy,'BTLF',1.)
call IssueTargetOrder(dummy,"acidbomb",target)
//Random Effect
if i <= 20 then//Reduced mana
call SetUnitState(target, UNIT_STATE_MANA, GetUnitState(target,UNIT_STATE_MANA)- GetRandomReal(50,GetUnitState(target,UNIT_STATE_MANA)) )
elseif i> 20 and i <= 50 then
set dummy = CreateUnit(owner,'o00D',x,y,0.)//Stun
call UnitApplyTimedLife(dummy,'BTLF',1.)
call IssueTargetOrder(dummy,"thunderbolt",target)
elseif i > 50 and i <= 80 then
set dummy = CreateUnit(owner,'o00D',x,y,0.) //Slow movement
call UnitApplyTimedLife(dummy,'BTLF',1.)
call IssueTargetOrder(dummy,"acidbomb",target)
elseif i > 80 and i <= 100 then
set dummy = CreateUnit(owner,'o00E',x,y,0.) //slow attack
call UnitApplyTimedLife(dummy,'BTLF',1.)
call IssueTargetOrder(dummy,"acidbomb",target)
endif
//Ion particle Fx
call IonAddFx(target)
endif
set owner = null
set dummy = null
endfunction
private function IonCheckAttack takes nothing returns boolean
if GetUnitAbilityLevel(GetAttacker(),IONID1)>=1 or GetUnitAbilityLevel(GetAttacker(),IONID2)>=1then
call IonDealAttack(GetAttacker(),GetTriggerUnit())
endif
return false
endfunction
public function init takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
call RegisterSpellFinishResponse(IMW_SPELL,CastIonicMineWall)
call TriggerRegisterAnyUnitEventBJ(t1, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition(t1, Condition(function CheckMineId))
call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition(t2, Condition(function IonCheckAttack))
endfunction
endscope
//TESH.scrollpos=54
//TESH.alwaysfold=0
scope microblackhole initializer init
globals
private constant real TIMEOUT = 1. //Interval to check enemy ships and damage the nearest
private constant real TIMEOUT2 = 0.05 //Interval for the speed of movement of pull
private constant real DELTA_SPEED = 0.5
private constant integer SPEED = 1 //Speed of pull
private constant integer DUR = 20 //Number of interval for Timeout
private constant integer SPELL = 'A01I' //The spell
private constant real AOEDMG = 75. //Aoe for dmg
private constant real AOEPULL = 500. //Aoe for pull effect
private constant integer RESEARCH = 'R006' //For the damage coefficient
private constant real DMGCOEFF = 30 //*RESEARCH=Total dmg dealt per interval
private constant integer DUMMYID = 'o00J' //The dummy for the blackhole fx
private constant real MANACOST = 400 //If the spell is cancelled, give back this amount of mana
private constant integer IRONCOST = 100 //Spell works only if there is at least this iron cost
//globals for the unit group enum
private player CasterOwner = null
private real X = 0.
private real Y = 0.
endglobals
private struct str2
unit target
real angle
integer distance
integer i
endstruct
private function LoopPull takes nothing returns nothing
local timer t = GetExpiredTimer()
local str2 dat = GetTimerData(t)
local real newX = GetUnitX(dat.target) + DELTA_SPEED*SPEED*Cos(dat.angle)
local real newY = GetUnitY(dat.target) + DELTA_SPEED*SPEED*Sin(dat.angle)
if (dat.i < dat.distance) and GetUnitState(dat.target, UNIT_STATE_LIFE) > 0 then
set dat.i = dat.i + 1
call SetUnitX(dat.target, newX)
call SetUnitY(dat.target, newY)
else
call SetUnitPathing( dat.target, true)
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
private function IniPull takes unit target, real x1, real y1, real x2, real y2 returns nothing
local timer t = NewTimer()
local str2 dat = str2.create()
set dat.target = target
call SetUnitPathing(dat.target, false)
set dat.angle = Atan2((y2 -y1), (x2 - x1))
set dat.distance =R2I(SquareRoot((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))/SPEED)
set dat.i = 0
call SetTimerData(t, dat)
call TimerStart (t, TIMEOUT2, true, function LoopPull)
endfunction
private function FilterNearbyEnemy takes nothing returns boolean
if IsUnitEnemy(GetFilterUnit(),CasterOwner)==true and IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE)==false and IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD)==false then
call IniPull(GetFilterUnit(),GetUnitX(GetFilterUnit()),GetUnitY(GetFilterUnit()),X,Y)
endif
return true
endfunction
private struct str
unit caster
integer i
player owner
real xtarget
real ytarget
real dmg
endstruct
private function LoopDamageAndIniPull takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
if dat.i < DUR and GetUnitState(dat.caster, UNIT_STATE_LIFE) > 0 then
set dat.i = dat.i + 1
set CasterOwner = dat.owner //For Filter, global is needed
set X = dat.xtarget //same
set Y = dat.ytarget //same
call GroupEnumUnitsInRange(ENUM_GROUP,dat.xtarget,dat.ytarget,AOEPULL,Filter(function FilterNearbyEnemy))
call UnitDamageEnemies(dat.caster,AOEDMG,dat.xtarget,dat.ytarget,dat.dmg)
else
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
private function IniBlackHole takes unit caster, real x, real y returns nothing
local timer t = NewTimer()
local str dat = str.create()
set dat.caster = caster
set dat.owner = GetOwningPlayer(dat.caster)
set dat.i = 0
set dat.xtarget = x
set dat.ytarget = y
set dat.dmg = DMGCOEFF * GetPlayerTechCount(dat.owner, RESEARCH, true) //Improved physic weapons
call SetTimerData(t, dat)
call TimerStart (t, TIMEOUT, true, function LoopDamageAndIniPull )
endfunction
private function Actions takes nothing returns nothing
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
if GetPlayerState(owner,PLAYER_STATE_RESOURCE_LUMBER)>= IRONCOST then
call SetResource(owner,0,-IRONCOST)
call UnitApplyTimedLife(CreateUnit(owner,DUMMYID,SpellEvent.TargetX,SpellEvent.TargetY,0.),'BTLF',DUR)
call IniBlackHole(SpellEvent.CastingUnit,SpellEvent.TargetX,SpellEvent.TargetY)
else
call UnitRemoveAbility(SpellEvent.CastingUnit,SPELL)
call UnitAddAbility(SpellEvent.CastingUnit,SPELL)
call DisplayTextToPlayer( owner, 0, 0, "Not enough Iron" )
call SetUnitState(SpellEvent.CastingUnit,UNIT_STATE_MANA,GetUnitState(SpellEvent.CastingUnit,UNIT_STATE_MANA)+MANACOST)
call ErrorSound(owner)
endif
set owner = null
endfunction
public function init takes nothing returns nothing
call RegisterSpellFinishResponse(SPELL,Actions)
endfunction
endscope
//TESH.scrollpos=3
//TESH.alwaysfold=0
scope msminelayer initializer init
globals
private constant real TIMEOUT = 5.00
private constant integer ID = 'n006'
private constant integer MST = 'E023'
endglobals
private struct structure
unit caster
player owner
endstruct
private function Action takes nothing returns nothing
local timer t = GetExpiredTimer()
local structure dat = GetTimerData(t)
local real x = GetUnitX(dat.caster)
local real y = GetUnitY(dat.caster)
if GetUnitState(dat.caster, UNIT_STATE_LIFE) > 0 then
call CreateUnit(dat.owner,ID,x,y,0.00)
else
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
private function IniSpawn takes unit caster returns nothing
local timer t = NewTimer()
local structure dat = structure.create()
set dat.caster = caster
set dat.owner = GetOwningPlayer(dat.caster)
call SetTimerData(t, dat)
call TimerStart (t, TIMEOUT, true, function Action )
endfunction
private function Conditions takes nothing returns boolean
if GetUnitTypeId(GetTriggerUnit())==MST then
call IniSpawn(GetTriggerUnit())
endif
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterEnterRectSimple(t, bj_mapInitialPlayableArea)
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=68
//TESH.alwaysfold=0
scope AllMissile initializer init
globals
//generic
integer SOUND_TORPEDO
private constant integer AUTODESTRUCTION = 'A04P'
private constant real DELTA_SPEED = 0.6
private constant real TIMEOUT = 0.05
private constant integer RESEARCH = 'R006'//improved physic weapons
private constant real LIFESPAN = 2.5 //lifespan of the missile
//Torpedoes
private constant integer TORPEDO_SPELL = 'A006'
private constant real TORPEDO_DAMAGEBASE = 100. //base damage
private constant real TORPEDO_DAMAGECOEFF = 50. //total dmg = base+coeff*level of research
private constant integer TORPEDO_LUMBERCOST = 100 //cost of the spell
private constant real TORPEDO_MANACOST = 400. //mana to reload if not enough iron
private constant integer TORPEDO_ID = 'n002' //id of the missile
private constant real TORPEDO_AOE = 150. //aoe of the dmg dealt
//Torpedo Overload
private constant integer TORPEDO_OVERLOAD_SPELL = 'A023'
private constant integer TORPEDO_OVERLOAD_LUMBERCOST = 400 //cost of the spell
private constant real TORPEDO_OVERLOAD_MANACOST = 400. //mana to reload if not enough iron
//Missile FlushGameCacheprivate constant integer MISSILE_SPELL = 'A021'
private constant real MISSILE_DAMAGEBASE = 20. //base damage
private constant real MISSILE_DAMAGECOEFF = 20. //total dmg = base+coeff*level of research
private constant integer MISSILE_LUMBERCOST = 400 //cost of the spell
private constant real MISSILE_MANACOST = 400. //mana to reload if not enough iron
private constant integer MISSILE_ID = 'n00A' //id of the missile
private constant real MISSILE_AOE = 100. //aoe of the dmg dealt
private constant real MISSILE_TIMEOUT = 0.25 //interval between each dual missile fired
private constant integer MISSILE_COUNT = 8 //*2 =>2*Counts missiles spawned
private constant integer MISSILE_SPELL = 'A021'
endglobals
private struct s_missile
unit mis = null
real angle = 0.
real distance = 0.
real damage = 0.
real radius = 0.
boolean withFx = false
integer countmove = 0
endstruct
private function RunUpdate takes nothing returns nothing
local timer t = GetExpiredTimer()
local s_missile this = GetTimerData(t)
local real newX = GetUnitX(this.mis) + DELTA_SPEED*this.countmove*Cos(this.angle)
local real newY = GetUnitY(this.mis) + DELTA_SPEED*this.countmove*Sin(this.angle)
if this.countmove < this.distance and GetUnitState(this.mis,UNIT_STATE_LIFE)>0 then
set this.countmove = this.countmove + 1
call SetUnitX(this.mis, newX)
call SetUnitY(this.mis, newY)
else
call ReleaseTimer(t)
if this.withFx == true then
call DestroyEffect(AddSpecialEffect("Units\\NightElf\\Wisp\\WispExplode.mdl",GetUnitX(this.mis),GetUnitY(this.mis)))
endif
call UnitDamageEnemiesKnb(this.mis,this.radius,GetUnitX(this.mis),GetUnitY(this.mis),this.damage,400,2)
call KillUnit(this.mis)
call this.destroy()
endif
endfunction
private function InitializeMissile takes unit missile, real destX, real destY,real damage,real radius,boolean withFx returns nothing
local s_missile this = s_missile.create()
local timer t = NewTimer()
local real x = GetUnitX(missile)
local real y = GetUnitY(missile)
set this.mis = missile
call RunSoundOnUnit(SOUND_TORPEDO,this.mis)
set this.withFx = withFx
set this.damage = damage
set this.radius = radius
set this.angle = Atan2((destY-y), (destX-x))
set this.distance =R2I(SquareRoot(destX-x)*(destX-x)+(destY-y)*(destY-y))
call SetUnitFacing(this.mis,this.angle*bj_RADTODEG)
call SetUnitPathing(this.mis, false)
set this.countmove = 0
call UnitAddAbility(this.mis,AUTODESTRUCTION)
call SetTimerData(t, this )
call TimerStart(t,TIMEOUT, true,function RunUpdate)
endfunction
private function RestoreStats takes unit caster,integer spell, real mana returns nothing
local player owner = GetOwningPlayer(caster)
call UnitRemoveAbility(caster,spell)
call UnitAddAbility(caster,spell)
call DisplayTextToPlayer( owner, 0, 0, "Not enough Iron" )
call SetUnitState(caster,UNIT_STATE_MANA,GetUnitState(caster,UNIT_STATE_MANA)+mana)
call ErrorSound(owner)
set owner = null
endfunction
private struct str
unit caster
player owner
integer i
real damage
real x
real y
unit dummy
method destroy takes nothing returns nothing
set .caster = null
set .owner = null
set .dummy = null
endmethod
endstruct
private function SpawnMissile takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
local real x = GetUnitX(dat.caster)
local real y = GetUnitY(dat.caster)
local real x1 = 0.
local real y1 = 0.
local real x2 = 0.
local real y2 = 0.
local real angle = GetUnitFacing(dat.caster)
if dat.i < MISSILE_COUNT then
set dat.i = dat.i + 1
set angle = GetUnitFacing(dat.caster)
set x1 = x + 25.*Cos((angle+90)*bj_DEGTORAD)
set y1 = y + 25.*Sin((angle+90)*bj_DEGTORAD)
set x2 = dat.x + 25.*Cos((angle+90)*bj_DEGTORAD)
set y2 = dat.y + 25.*Sin((angle+90)*bj_DEGTORAD)
set dat.dummy = CreateUnit(dat.owner,MISSILE_ID,x1,y1,angle)
call UnitApplyTimedLife(dat.dummy,'BTLF',LIFESPAN)
call InitializeMissile(dat.dummy,x2,y2,dat.damage,MISSILE_AOE,false)
set x1 = x + 25.*Cos((angle-90)*bj_DEGTORAD)
set y1 = y + 25.*Sin((angle-90)*bj_DEGTORAD)
set x2 = dat.x + 25.*Cos((angle-90)*bj_DEGTORAD)
set y2 = dat.y + 25.*Sin((angle-90)*bj_DEGTORAD)
set dat.dummy = CreateUnit(dat.owner,MISSILE_ID,x1,y1,angle)
call UnitApplyTimedLife(dat.dummy,'BTLF',LIFESPAN)
call InitializeMissile(dat.dummy,x2,y2,dat.damage,MISSILE_AOE,false)
else
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
private function MissileFlushRun takes unit caster, real x, real y returns nothing
local timer t = NewTimer()
local str dat = str.create()
set dat.caster = caster
set dat.owner = GetOwningPlayer(dat.caster)
set dat.damage = MISSILE_DAMAGEBASE+MISSILE_DAMAGECOEFF*GetPlayerTechCount(dat.owner, RESEARCH, true)
set dat.i = 0
set dat.x = x
set dat.y = y
call SetTimerData(t, dat)
call TimerStart (t,MISSILE_TIMEOUT, true, function SpawnMissile )
endfunction
private function MissileFlushCheck takes nothing returns nothing
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
if GetPlayerState(owner,PLAYER_STATE_RESOURCE_LUMBER)>= MISSILE_LUMBERCOST then
call SetResource(owner,0,-MISSILE_LUMBERCOST)
call MissileFlushRun(SpellEvent.CastingUnit,SpellEvent.TargetX,SpellEvent.TargetY)
else
call RestoreStats(SpellEvent.CastingUnit,MISSILE_SPELL,MISSILE_MANACOST)
endif
endfunction
private function TorpedoOverload takes nothing returns nothing
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
local real dmg = TORPEDO_DAMAGEBASE+TORPEDO_DAMAGECOEFF*GetPlayerTechCount(owner, RESEARCH, true)
local unit dummy = null
local real x = GetUnitX(SpellEvent.CastingUnit)
local real y = GetUnitY(SpellEvent.CastingUnit)
local real x1 = 0.
local real y1 = 0.
local real x2 = 0.
local real y2 = 0.
local real angle = GetUnitFacing(SpellEvent.CastingUnit)
if GetPlayerState(owner,PLAYER_STATE_RESOURCE_LUMBER)>= TORPEDO_OVERLOAD_LUMBERCOST then
call SetResource(owner,0,-TORPEDO_OVERLOAD_LUMBERCOST)
set x1 = x + 25.*Cos(angle+90)
set y1 = y + 25.*Sin(angle+90)
set x2 = SpellEvent.TargetX + 25.*Cos(angle+90)
set y2 = SpellEvent.TargetY + 25.*Sin(angle+90)
set dummy = CreateUnit(owner,TORPEDO_ID,x1,y1,angle)
call UnitApplyTimedLife(dummy,'BTLF',LIFESPAN)
call InitializeMissile(dummy,x2,y2,dmg,TORPEDO_AOE,true)
set x1 = x + 50.*Cos(angle+90)
set y1 = y + 50.*Sin(angle+90)
set x2 = SpellEvent.TargetX + 50.*Cos(angle+90)
set y2 = SpellEvent.TargetY + 50.*Sin(angle+90)
set dummy = CreateUnit(owner,TORPEDO_ID,x1,y1,angle)
call UnitApplyTimedLife(dummy,'BTLF',LIFESPAN)
call InitializeMissile(dummy,x2,y2,dmg,TORPEDO_AOE,true)
set x1 = x + 25.*Cos(angle-90)
set y1 = y + 25.*Sin(angle-90)
set x2 = SpellEvent.TargetX + 25.*Cos(angle-90)
set y2 = SpellEvent.TargetY + 25.*Sin(angle-90)
set dummy = CreateUnit(owner,TORPEDO_ID,x1,y1,angle)
call UnitApplyTimedLife(dummy,'BTLF',LIFESPAN)
call InitializeMissile(dummy,x2,y2,dmg,TORPEDO_AOE,true)
set x1 = x + 50.*Cos(angle-90)
set y1 = y + 50.*Sin(angle-90)
set x2 = SpellEvent.TargetX + 50.*Cos(angle-90)
set y2 = SpellEvent.TargetY + 50.*Sin(angle-90)
set dummy = CreateUnit(owner,TORPEDO_ID,x1,y1,angle)
call UnitApplyTimedLife(dummy,'BTLF',LIFESPAN)
call InitializeMissile(dummy,x2,y2,dmg,TORPEDO_AOE,true)
else
call RestoreStats(SpellEvent.CastingUnit,TORPEDO_OVERLOAD_SPELL,TORPEDO_OVERLOAD_MANACOST)
endif
set dummy = null
set owner = null
endfunction
private function TorpedoTurretRun takes unit turret, real x2, real y2 returns nothing
local real x1 = GetUnitX(turret)
local real y1 = GetUnitY(turret)
local player owner = GetOwningPlayer(turret)
local real dmg = TORPEDO_DAMAGEBASE+TORPEDO_DAMAGECOEFF*GetPlayerTechCount(owner, RESEARCH, true)
local unit dummy = CreateUnit(owner,TORPEDO_ID,x1,y1,GetUnitFacing(turret))
call UnitApplyTimedLife(dummy,'BTLF',LIFESPAN)
call InitializeMissile(dummy,x2,y2,dmg,TORPEDO_AOE,true)
set owner = null
set dummy = null
endfunction
private function TorpedoTurretCheck takes nothing returns boolean
local unit turret = GetAttacker()
local unit target = GetTriggerUnit()
local integer turretId = GetUnitTypeId(turret)
if turretId == 'h005' or turretId == 'h01I' or turretId == 'E034' then
call TorpedoTurretRun(turret,GetUnitX(target),GetUnitY(target))
endif
set turret = null
set target = null
return false
endfunction
private function TorpedoSingle takes nothing returns nothing
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
local real dmg = TORPEDO_DAMAGEBASE+TORPEDO_DAMAGECOEFF*GetPlayerTechCount(owner, RESEARCH, true)
local unit dummy = null
local real x1 = GetUnitX(SpellEvent.CastingUnit)
local real y1 = GetUnitY(SpellEvent.CastingUnit)
local real x2 = SpellEvent.TargetX
local real y2 = SpellEvent.TargetY
if GetPlayerState(owner,PLAYER_STATE_RESOURCE_LUMBER)>= TORPEDO_LUMBERCOST then
call SetResource(owner,0,-TORPEDO_LUMBERCOST)
set dummy = CreateUnit(owner,TORPEDO_ID,x1,y1,GetUnitFacing(SpellEvent.CastingUnit))
call UnitApplyTimedLife(dummy,'BTLF',LIFESPAN)
call InitializeMissile(dummy,x2,y2,dmg,TORPEDO_AOE,true)
else
call RestoreStats(SpellEvent.CastingUnit,TORPEDO_SPELL,TORPEDO_MANACOST)
endif
set owner = null
set dummy = null
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
set SOUND_TORPEDO = DefineSound("sound_torpedolaunch.wav",2000,false,true)
call AbilityPreload(AUTODESTRUCTION)
call RegisterSpellFinishResponse(TORPEDO_SPELL,TorpedoSingle)
call RegisterSpellFinishResponse(TORPEDO_OVERLOAD_SPELL,TorpedoOverload)
call RegisterSpellFinishResponse(MISSILE_SPELL,MissileFlushCheck)
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition(t, Condition(function TorpedoTurretCheck))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Mooring initializer init
//warn to avoid conflicts with Steal: remove attack
globals
private constant real MAX_LINK_DISTANCE = 200.
private constant real LIGHTNING_Z = 15.
constant integer UNLEASH = 'A03M'
constant integer MOORING = 'A035'
private constant real TIMEOUT = 0.05
endglobals
private struct str
unit caster
unit target = null
lightning lbolt = null
timer t = null
private static method createFilter takes unit u returns boolean
return GetUnitAbilityLevel(u,MOORING)>=1
endmethod
private method onCreate takes nothing returns nothing
set .lbolt = null
set .target = null
set .caster = me
set .t = null
endmethod
implement AutoCreate
private method onDestroy takes nothing returns nothing
set .lbolt = null
set .target = null
set .caster = null
set .t = null
endmethod
implement AutoDestroy
endstruct
private function Update takes nothing returns nothing
local timer t = GetExpiredTimer()
local str this = GetTimerData(t)
local real dx
local real dy
local real angle
if GetUnitState(this.target,UNIT_STATE_LIFE)>0 and GetUnitState(this.caster,UNIT_STATE_LIFE)>0 then
set dx = GetUnitX(this.target)-GetUnitX(this.caster)
set dy = GetUnitY(this.target)-GetUnitY(this.caster)
if( dx*dx+dy*dy > MAX_LINK_DISTANCE*MAX_LINK_DISTANCE )then
set angle = Atan2(dy,dx)
set dx = GetUnitX(this.caster) + MAX_LINK_DISTANCE*Cos(angle)
set dy = GetUnitY(this.caster) + MAX_LINK_DISTANCE*Sin(angle)
call SetUnitPosition(this.target, dx, dy )
endif
call MoveLightningEx(this.lbolt, true, GetUnitX(this.caster), GetUnitY(this.caster), GetUnitFlyHeight(this.caster)+LIGHTNING_Z, GetUnitX(this.target), GetUnitY(this.target), GetUnitFlyHeight(this.target)+LIGHTNING_Z )
else
call ReleaseTimer(t)
call DestroyLightning(this.lbolt)
call SetUnitPathing(this.target,true)
call UnitRemoveAbility(this.caster,UNLEASH)
call UnitAddAbility(this.caster,MOORING)
call UnitRemoveAbility(this.caster,GARN)
endif
endfunction
private function Hook takes nothing returns nothing
local str this = str[SpellEvent.CastingUnit]
set this.caster = SpellEvent.CastingUnit
set this.target = SpellEvent.TargetUnit
call UnitAddAbility(this.target, GARN)
set this.lbolt = AddLightningEx( "LEAS", true, GetUnitX(this.caster), GetUnitY(this.caster), GetUnitFlyHeight(this.caster)+LIGHTNING_Z, GetUnitX(this.target), GetUnitY(this.target), GetUnitFlyHeight(this.target)+LIGHTNING_Z )
call SetUnitPathing(this.target,false)
call UnitRemoveAbility(this.caster,MOORING)
call UnitAddAbility(this.caster,UNLEASH)
call UnitAddAbility(this.caster,GARN)
set this.t = NewTimer()
call SetTimerData( this.t, this )
call TimerStart( this.t, TIMEOUT, true, function Update )
endfunction
private function Unleash takes nothing returns nothing
local str this = str[SpellEvent.CastingUnit]
call ReleaseTimer(this.t)
call DestroyLightning(this.lbolt)
call SetUnitPathing(this.target,true)
call UnitRemoveAbility(this.caster,UNLEASH)
call UnitAddAbility(this.caster,MOORING)
call UnitRemoveAbility(this.caster,GARN)
endfunction
public function init takes nothing returns nothing
call AbilityPreload(UNLEASH)
call AbilityPreload(MOORING)
call RegisterSpellFinishResponse(MOORING,Hook)
call RegisterSpellFinishResponse(UNLEASH,Unleash)
endfunction
endscope
//TESH.scrollpos=45
//TESH.alwaysfold=0
scope naniteinjection initializer init
globals
private constant integer ID = 'o00M'
private constant integer SPELL = 'A01W'
private constant real WAITTIME = 6.00
private constant integer PORTAL_ID = 'OTsp'
private constant real DISTANCE = 200.
endglobals
private struct s_data
destructable portal_1
destructable portal_2
private method onCreate takes nothing returns nothing
set .portal_1 = null
set .portal_2 = null
endmethod
implement AutoCreate
private method onDestroy takes nothing returns nothing
call KillDestructable(.portal_1)
call KillDestructable(.portal_2)
set .portal_1 = null
set .portal_2 = null
endmethod
implement AutoDestroy
endstruct
private function PolarOffsetX takes real x,real dist,real rad returns real
return x + dist*Cos(rad)
endfunction
private function PolarOffsetY takes real x,real dist,real rad returns real
return x + dist*Sin(rad)
endfunction
private function SpellEffect takes unit ship, real targetX, real targetY returns nothing
local s_data s = s_data[ship] // instance de struct réservée pour l'unit
local real x = GetUnitX(ship)
local real y = GetUnitY(ship)
local real angle = Atan2(y-targetX,x-targetY)
set s.portal_1 = CreateDestructable(PORTAL_ID,PolarOffsetX(x,-DISTANCE,angle),PolarOffsetY(y,-DISTANCE,angle),angle*bj_RADTODEG,0.5,0)
set s.portal_2 = CreateDestructable(PORTAL_ID,PolarOffsetX(targetX,DISTANCE,angle),PolarOffsetY(targetY,DISTANCE,angle),angle*bj_RADTODEG,0.5,0)
call SetDestructableAnimation(s.portal_1,"birth")
call SetDestructableAnimation(s.portal_2,"birth")
endfunction
private function SpellFinish takes unit ship, real x, real y returns nothing
local s_data s = s_data[ship]
call SetUnitX(ship,x)
call SetUnitY(ship,y)
call s.destroy()
endfunction
private struct str
unit target
real x
real y
endstruct
private function Wait takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
call SpellFinish(dat.target,dat.x,dat.y)
call ReleaseTimer(t)
call dat.destroy()
endfunction
private function Actions takes nothing returns nothing
local timer t = NewTimer()
local str dat = str.create()
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
local real x1 = GetUnitX(SpellEvent.CastingUnit)
local real y1 = GetUnitY(SpellEvent.CastingUnit)
local real x2 = GetUnitX(SpellEvent.TargetUnit)
local real y2 = GetUnitY(SpellEvent.TargetUnit)
local real x = GetRandomReal(GetRectMinX(bj_mapInitialPlayableArea),GetRectMaxX(bj_mapInitialPlayableArea))
local real y = GetRandomReal(GetRectMinY(bj_mapInitialPlayableArea),GetRectMaxY(bj_mapInitialPlayableArea))
local unit dummy = CreateUnit(owner,ID,x1,y1,0.00)
call UnitApplyTimedLife(dummy,'BTLF',3.00)
call IssuePointOrder(dummy,"healingspray",x2,y2)
set dat.target = SpellEvent.TargetUnit
set dat.x = x
set dat.y = y
call SpellEffect(SpellEvent.TargetUnit,dat.x,dat.y)
call SetTimerData(t, dat)
call TimerStart (t, WAITTIME,false, function Wait)
set owner = null
set dummy = null
endfunction
public function init takes nothing returns nothing
call RegisterSpellFinishResponse(SPELL,Actions)
endfunction
endscope
//TESH.scrollpos=9
//TESH.alwaysfold=0
scope nukeset initializer init
globals
private constant integer SPELL = 'A038'
private constant integer DUR = 30 //number of interval before explosion
private constant integer BOMBID = 'n009' //the bomb unit
private constant integer DUMMYID = 'o00P' //the explosion effect unit
private constant real TIMEOUT = 1. //interval of wait cooldown
private constant integer RESEARCH = 'R006' //Improved physic weapons
private constant real AOE = 750. //aoe of the explosion
private constant real DAMAGEBASE = 1000. //basic damage amount
private constant real DAMAGECOEFF = 500. //total damage = DAMAGEBASE+DAMAGECOEFF*level of RESEARCH
endglobals
private struct str
unit bomb
player owner
real dmg
integer i
endstruct
private function Wait takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
if dat.i < DUR and GetUnitState(dat.bomb,UNIT_STATE_LIFE)> 0 then
call Text(dat.bomb,false,"Explosion:"+I2S(DUR-dat.i)+"seconds left")
set dat.i = dat.i + 1
else
if dat.i >= DUR and GetUnitState(dat.bomb,UNIT_STATE_LIFE)> 0 then
call UnitApplyTimedLife(CreateUnit(dat.owner,DUMMYID,GetUnitX(dat.bomb),GetUnitY(dat.bomb),0.00),'BTLF',10.00)
call UnitDamageAll(dat.bomb,AOE,GetUnitX(dat.bomb),GetUnitY(dat.bomb),dat.dmg)
call RemoveUnit(dat.bomb)
endif
call RemoveUnit(dat.bomb)
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
private function Actions takes nothing returns nothing
local timer t = NewTimer()
local str dat = str.create()
set dat.owner = GetOwningPlayer(SpellEvent.CastingUnit)
set dat.bomb = CreateUnit(dat.owner,BOMBID,GetUnitX(SpellEvent.CastingUnit),GetUnitY(SpellEvent.CastingUnit),0.)
set dat.dmg = DAMAGEBASE+DAMAGECOEFF*GetPlayerTechCount(dat.owner,RESEARCH,true)
set dat.i = 0
call Text(dat.bomb,false,"Explosion:"+"30 seconds left")
call SetTimerData(t, dat)
call TimerStart (t,TIMEOUT, true, function Wait)
endfunction
public function init takes nothing returns nothing
call RegisterSpellFinishResponse(SPELL,Actions)
endfunction
endscope
//TESH.scrollpos=20
//TESH.alwaysfold=0
scope ParticleShield initializer init
globals
private constant integer PARTSHIELD = 'A024'
private constant integer SHIELDEC = 'A043'
private constant real AOETAUNT = 350.
private constant real AOESHIELD = 250.
private constant real TIMEOUT = 1.
private constant integer DUR = 30
private player Owner = null
private unit Caster = null
endglobals
private function TakeDamageConditions takes nothing returns boolean
local unit damaged = GetTriggerUnit()
local real damage = GetEventDamage()
if GetUnitAbilityLevel(damaged,SHIELDEC) >= 1 then
if GetUnitAbilityLevel(damaged,PARTSHIELD)<= 0 then
call SetUnitState(damaged,UNIT_STATE_LIFE,GetUnitState(damaged,UNIT_STATE_LIFE)+0.50*damage)
else
call SetUnitState(damaged,UNIT_STATE_LIFE,GetUnitState(damaged,UNIT_STATE_LIFE)-0.50*damage)
endif
endif
return false
endfunction
private struct str
unit ship = null
unit shieldSource = null
integer count = 0
trigger trig = null
private method onCreate takes nothing returns nothing
set .shieldSource = null
set .ship = me
set .trig = null
endmethod
implement AutoCreate
private method onDestroy takes nothing returns nothing
set .shieldSource = null
set .ship = null
set .trig = null
endmethod
implement AutoDestroy
endstruct
private function Update takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
if dat.count < DUR and GetUnitState(dat.ship,UNIT_STATE_LIFE)>0 and GetUnitState(dat.shieldSource,UNIT_STATE_LIFE)>0 then
set dat.count = dat.count + 1
else
call ReleaseTimer(t)
if GetUnitAbilityLevel(dat.ship,SHIELDEC)>=1 then
call UnitRemoveAbility(dat.ship,SHIELDEC)
endif
call DisableTrigger(dat.trig)
call DestroyTrigger(dat.trig)
call dat.destroy()
endif
endfunction
private function AddShipToParticleShield takes unit ship, unit shieldSource returns nothing
local timer t = NewTimer()
local str dat = str[ship]
set dat.ship = ship
set dat.shieldSource = shieldSource
set dat.count = 0
if GetUnitAbilityLevel(dat.ship,SHIELDEC)<= 0 then
call UnitAddAbility(dat.ship,SHIELDEC)
endif
set dat.trig = CreateTrigger()
call TriggerRegisterUnitEvent(dat.trig,dat.ship, EVENT_UNIT_DAMAGED )
call TriggerAddCondition(dat.trig, Condition(function TakeDamageConditions))
call SetTimerData(t, dat)
call TimerStart(t,TIMEOUT, true, function Update )
endfunction
private function FilterAndAddAbility takes nothing returns boolean
if IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL)==false and IsUnitAlly(GetFilterUnit(),Owner)==true then
call AddShipToParticleShield(GetFilterUnit(),Caster)
endif
return true
endfunction
private function FilterAndTaunt takes nothing returns boolean
if IsUnitEnemy(GetFilterUnit(),Owner)==true then
call IssueTargetOrder(GetFilterUnit(),"attack",Caster)
endif
return true
endfunction
private function CastSpell takes nothing returns nothing
local real x = GetUnitX(SpellEvent.CastingUnit)
local real y = GetUnitY(SpellEvent.CastingUnit)
set Caster = SpellEvent.CastingUnit
set Owner = GetOwningPlayer(SpellEvent.CastingUnit)
call GroupEnumUnitsInRange(ENUM_GROUP,x,y,AOETAUNT,Filter(function FilterAndTaunt))
call GroupEnumUnitsInRange(ENUM_GROUP,x,y,AOESHIELD,Filter(function FilterAndAddAbility))
endfunction
public function init takes nothing returns nothing
call AbilityPreload(SHIELDEC)
call RegisterSpellFinishResponse(PARTSHIELD,CastSpell)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope PlasmaStorm initializer init
globals
private constant integer ID1 = 'o00R'
private constant integer ID2 = 'o00S'
private constant integer SPELL = 'A03E'
private constant real AOE_SPAWN = 250.
private constant real MAXHEIGHT = 200.
private constant string FX1 = "war3mapImported\\fx_stomp_squished.mdx"
private constant string FX2 = "war3mapImported\\light.mdx"
private constant integer RESEARCH = 'R005'//improved plasma weapons
private constant real DAMAGEBASE = 100. //base damage
private constant real DAMAGECOEFF = 100. //total dmg = base+coeff*level of research
private constant real AOE_DMG = 125.
endglobals
private function ParticleDeath takes unit particle returns nothing
local player owner = GetOwningPlayer(particle)
local real x = GetUnitX(particle)
local real y = GetUnitY(particle)
local real dmg = DAMAGEBASE+DAMAGECOEFF*GetPlayerTechCount(owner,RESEARCH, true)
call DestroyEffect(AddSpecialEffect(FX2,x,y))
call DestroyEffect(AddSpecialEffect(FX1,x,y))
call UnitDamageEnemiesKnb(particle,AOE_DMG,x,y,dmg,400,2)
set owner = null
endfunction
private function ParticleCheck takes nothing returns boolean
if GetUnitTypeId(GetTriggerUnit()) == ID1 or GetUnitTypeId(GetTriggerUnit())==ID2 then
call ParticleDeath(GetTriggerUnit())
endif
return false
endfunction
private function CastSpell takes nothing returns nothing
local integer i = 0
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
local real x = SpellEvent.TargetX
local real y = SpellEvent.TargetY
local unit dummy = CreateUnit(owner,ID1,SpellEvent.TargetX,SpellEvent.TargetY,bj_UNIT_FACING)
call UnitApplyTimedLife( dummy,'BTLF',8.)
call SetUnitFlyHeight( dummy, MAXHEIGHT,400.)
loop
set i = i + 1
exitwhen i > 30
set x = SpellEvent.TargetX + GetRandomReal(-AOE_SPAWN,AOE_SPAWN)
set y = SpellEvent.TargetY + GetRandomReal(-AOE_SPAWN,AOE_SPAWN)
set dummy = CreateUnit(owner, ID2, x,y, bj_UNIT_FACING )
call UnitApplyTimedLife( dummy, 'BTLF', 5.00+0.10*i )
call SetUnitFlyHeight( dummy, MAXHEIGHT, GetRandomReal(100.,400.))
call IssuePointOrder(dummy,"move",SpellEvent.TargetX,SpellEvent.TargetY)
endloop
set owner = null
set dummy = null
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call RegisterSpellFinishResponse(SPELL,CastSpell)
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition(t, Condition(function ParticleCheck))
endfunction
endscope
//TESH.scrollpos=100
//TESH.alwaysfold=0
library RecycleUnitsAndBuildings initializer init needs TimerUtils,TextDisplay,SpellEvent,Resource
globals
private constant integer RECYCLE_BUILDING = 'A00D'
private constant integer RECYCLE_UNIT = 'A01M'
private constant string C1 = "|cff008040"
private constant string C2 = "|cff80FFFF"
private constant string C = " |r"
private constant string FX = "Abilities\\Spells\\Orc\\Voodoo\\VoodooAuraTarget.mdl"
private constant real DURATION = 2.
private key GOLD_INDEX // juste des constant integer à valeur unique (chaque key à une valeur différente)
private key LUMBER_INDEX
private hashtable HashT
endglobals
//! textmacro t__RecycleSystem_Init takes UNIT_TYPE , UNIT_GOLD, UNIT_LUMBER
call SaveInteger(HashT,$UNIT_TYPE$,GOLD_INDEX,$UNIT_GOLD$)
call SaveInteger(HashT,$UNIT_TYPE$,LUMBER_INDEX,$UNIT_LUMBER$)
//! endtextmacro
private function SetCostVariables takes nothing returns nothing
//! runtextmacro t__RecycleSystem_Init("'h00M'","250", "5")
//! runtextmacro t__RecycleSystem_Init("'h00N'","150", "5")
//! runtextmacro t__RecycleSystem_Init("'h00O'","200", "5")
//! runtextmacro t__RecycleSystem_Init("'h01M'","400", "30")
//! runtextmacro t__RecycleSystem_Init("'h00C'","400", "30")
//! runtextmacro t__RecycleSystem_Init("'h00G'","400", "30")
//! runtextmacro t__RecycleSystem_Init("'h00H'","300", "10")
//! runtextmacro t__RecycleSystem_Init("'h01L'","400", "30")
//! runtextmacro t__RecycleSystem_Init("'h015'","900", "50")
//! runtextmacro t__RecycleSystem_Init("'h00L'","600", "150")
//! runtextmacro t__RecycleSystem_Init("'h00I'","800", "50")
//! runtextmacro t__RecycleSystem_Init("'h01H'","600", "150")
//! runtextmacro t__RecycleSystem_Init("'h00Y'","1000", "75")
//! runtextmacro t__RecycleSystem_Init("'h01D'","750", "75")
//! runtextmacro t__RecycleSystem_Init("'h00J'","1200", "150")
//! runtextmacro t__RecycleSystem_Init("'h01N'","1200", "150")
//! runtextmacro t__RecycleSystem_Init("'h01O'","2000", "100")
//! runtextmacro t__RecycleSystem_Init("'h00K'","1200", "100")
//! runtextmacro t__RecycleSystem_Init("'h00A'","2500", "300")
//! runtextmacro t__RecycleSystem_Init("'h00Z'","500", "0")
//! runtextmacro t__RecycleSystem_Init("'h00F'","500", "0")
//! runtextmacro t__RecycleSystem_Init("'h00P'","1500", "300")
//! runtextmacro t__RecycleSystem_Init("'h01C'","2000", "20")
//! runtextmacro t__RecycleSystem_Init("'h017'","2500", "300")
//! runtextmacro t__RecycleSystem_Init("'h00D'","3500", "400")
//! runtextmacro t__RecycleSystem_Init("'h006'","250", "50")
//! runtextmacro t__RecycleSystem_Init("'h00E'","4000", "500")
//! runtextmacro t__RecycleSystem_Init("'h007'","350", "100")
//! runtextmacro t__RecycleSystem_Init("'h018'","500", "200")
//! runtextmacro t__RecycleSystem_Init("'h016'","500", "200")
//! runtextmacro t__RecycleSystem_Init("'h005'","500", "200")
//! runtextmacro t__RecycleSystem_Init("'h00B'","5000", "600")
//! runtextmacro t__RecycleSystem_Init("'h01P'","6000", "700")
//! runtextmacro t__RecycleSystem_Init("'h00O'","2000", "500")
//! runtextmacro t__RecycleSystem_Init("'h008'","6000", "700")
//! runtextmacro t__RecycleSystem_Init("'n004'","1000", "100")
//! runtextmacro t__RecycleSystem_Init("'n005'","1000", "100")
//! runtextmacro t__RecycleSystem_Init("'h004'","200", "0")
//! runtextmacro t__RecycleSystem_Init("'h01R'","200", "0")
//! runtextmacro t__RecycleSystem_Init("'h00S'","500", "100")
//! runtextmacro t__RecycleSystem_Init("'h00T'","1000", "200")
//! runtextmacro t__RecycleSystem_Init("'hO1I'","500", "100")
//! runtextmacro t__RecycleSystem_Init("'h003'","200", "50")
//! runtextmacro t__RecycleSystem_Init("'h01K'","200", "50")
//! runtextmacro t__RecycleSystem_Init("'h01A'","200", "50")
//! runtextmacro t__RecycleSystem_Init("'h01B'","200", "50")
//! runtextmacro t__RecycleSystem_Init("'h014'","200", "50")
//! runtextmacro t__RecycleSystem_Init("'h019'","200", "50")
//! runtextmacro t__RecycleSystem_Init("'h002'","300", "50")
//! runtextmacro t__RecycleSystem_Init("'h011'","800", "100")
//! runtextmacro t__RecycleSystem_Init("'h012'","3500", "200")
//! runtextmacro t__RecycleSystem_Init("'h001'","150", "0")
//! runtextmacro t__RecycleSystem_Init("'h01E'","500", "50")
//! runtextmacro t__RecycleSystem_Init("'h010'","150", "0")
//! runtextmacro t__RecycleSystem_Init("'h01Q'","150", "0")
//! runtextmacro t__RecycleSystem_Init("'o00I'","3000", "500")
endfunction
private struct str
effect e
endstruct
private function WaitForEffect takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
call DestroyEffect(dat.e)
call ReleaseTimer(t)
call dat.destroy()
endfunction
private function RecycleBuilding takes nothing returns nothing
local integer casterId = GetUnitTypeId(SpellEvent.CastingUnit)
local integer randomGold = R2I(GetRandomReal(0.25,1.00)*LoadInteger(HashT,casterId,GOLD_INDEX))
local integer randomLumber = R2I(GetRandomReal(0.25,1.00)*LoadInteger(HashT,casterId,LUMBER_INDEX))
local timer t = NewTimer()
local str dat = str.create()
call Text(SpellEvent.CastingUnit,false,C1+I2S(randomGold)+"Pulsars"+C+" - "+C2+I2S(randomLumber)+"Iron"+C)
call SetResource(GetOwningPlayer(SpellEvent.CastingUnit),randomGold,randomLumber)
call UnitRemoveAbility(SpellEvent.CastingUnit,RECYCLE_BUILDING)
call UnitApplyTimedLife(SpellEvent.CastingUnit,'BTLF',DURATION)
set dat.e = AddSpecialEffectTarget(FX,SpellEvent.CastingUnit,"origin")
call SetTimerData(t, dat)
call TimerStart (t,DURATION, false, function WaitForEffect )
endfunction
private function RecycleUnit takes nothing returns nothing
local integer casterId = GetUnitTypeId(SpellEvent.TargetUnit)
local integer randomGold = R2I(GetRandomReal(0.25,1.00)*LoadInteger(HashT,casterId,GOLD_INDEX))
local integer randomLumber = R2I(GetRandomReal(0.25,1.00)*LoadInteger(HashT,casterId,LUMBER_INDEX))
local timer t = NewTimer()
local str dat = str.create()
call Text(SpellEvent.TargetUnit,false,C1+I2S(randomGold)+"Pulsars"+C+" - "+C2+I2S(randomLumber)+"Iron"+C)
call SetResource(GetOwningPlayer(SpellEvent.TargetUnit),randomGold,randomLumber)
call UnitRemoveAbility(SpellEvent.TargetUnit,RECYCLE_UNIT)
call UnitApplyTimedLife(SpellEvent.TargetUnit,'BTLF',DURATION)
set dat.e = AddSpecialEffectTarget(FX,SpellEvent.TargetUnit,"origin")
call SetTimerData(t, dat)
call TimerStart (t,DURATION, false, function WaitForEffect )
endfunction
private function init takes nothing returns nothing
call RegisterSpellCastResponse(RECYCLE_BUILDING,RecycleBuilding)
call RegisterSpellCastResponse(RECYCLE_UNIT,RecycleUnit)
set HashT = InitHashtable()
call SetCostVariables()
endfunction
endlibrary
//TESH.scrollpos=17
//TESH.alwaysfold=0
scope sspy initializer init
globals
private constant integer SPELL = 'A01Z'
private player Owner = null
private integer OwnerId = 0
private integer CasterOwnerId = 0
endglobals
private function FilterPlanets takes nothing returns boolean
if GetOwningPlayer(GetFilterUnit())==Owner and IsUnitType(GetFilterUnit(),UNIT_TYPE_TOWNHALL)==true then
if (GetLocalPlayer() == Player(CasterOwnerId)) then
call PingMinimap(GetUnitX(GetFilterUnit()),GetUnitY(GetFilterUnit()),5.00)
endif
call DisplayTextToPlayer(Player(CasterOwnerId),0.,0.,"A planet of "+PlayerColor[OwnerId]+GetPlayerName(Player(OwnerId))+" has been detected")
endif
return true
endfunction
function Ping takes integer whichCasterId,unit u,integer di, string s,integer whichFilteredId returns nothing
set Owner = Player(whichFilteredId)
set OwnerId = whichFilteredId
set CasterOwnerId = whichCasterId
call GroupEnumUnitsOfPlayer(ENUM_GROUP,Owner,Filter(function FilterPlanets))
endfunction
private function Actions takes nothing returns nothing
local integer i = 0
local unit caster = SpellEvent.CastingUnit
local player owner = GetOwningPlayer(caster)
local integer ownerId = GetPlayerId(owner)
call Clear(ownerId,"Select a Clan Target", null,0 )
loop
exitwhen i > MAXPLAYER
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING and IsPlayerEnemy(owner,Player(i)) then
call AddButton(ownerId,PlayerColor[i]+GetPlayerName(Player(i)), Ping, i, null, i)
endif
set i = i + 1
endloop
call AddButton(ownerId,"<Quit>", 0, i, null, i)
call Show(ownerId)
endfunction
public function init takes nothing returns nothing
call RegisterSpellFinishResponse(SPELL,Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Shrapnel initializer init
globals
private constant string FX = "Abilities\\Weapons\\GyroCopter\\GyroCopterImpact.mdl" //fx showed
private constant real AOE = 75.
private constant integer COUNT = 10 //Number of effect
private constant real TIMEOUT = 0.10 //effect dealt each timeout interval
private constant integer RESEARCH = 'R006' //Physic weapon research
private constant integer DMGCOEFF = 15 //*RESEARCH=Total dmg
private constant integer SPELL = 'A01D' //works only if the unit has this spell
private constant integer CHANCE = 15 //=>15% chances to deal the spell
endglobals
private struct str
unit target
unit caster
real x
real y
integer i
real dmg
endstruct
private function Action takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
local real newX = dat.x + GetRandomReal(-AOE,AOE)
local real newY = dat.y + GetRandomReal(-AOE,AOE)
if dat.i < COUNT and GetUnitState(dat.caster, UNIT_STATE_LIFE) > 0 then
set dat.i = dat.i + 1
call DestroyEffect(AddSpecialEffect(FX,newX,newY))
call UnitDamageEnemies(dat.caster,AOE,dat.x,dat.y,dat.dmg)
else
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
private function IniShrap takes unit caster, unit target returns nothing
local timer t = NewTimer()
local str dat = str.create()
set dat.caster = caster
set dat.target = target
set dat.i = 0
set dat.x = GetUnitX(dat.target)
set dat.y = GetUnitY(dat.target)
set dat.dmg = DMGCOEFF * GetPlayerTechCount(GetOwningPlayer(dat.caster), RESEARCH, true)
call SetTimerData(t, dat)
call TimerStart (t, TIMEOUT, true, function Action )
endfunction
private function Conditions takes nothing returns boolean
if GetUnitAbilityLevel(GetTriggerUnit(),SPELL)>=1 and GetRandomInt(0,100)<=CHANCE then
call IniShrap(GetTriggerUnit(),GetAttacker() )
endif
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=25
//TESH.alwaysfold=0
library StarEnergy needs AutoIndex, TimerUtils, TextDisplay
globals
private constant real RANGE = 400.
private constant integer OMEGA = 'h00U'
private constant integer SUN = 'o00G'
private constant real TIMEOUT = 5.
private constant integer ALPHA = 'h00Q'
private constant string FX = "Abilities\\Spells\\Items\\ClarityPotion\\ClarityTarget.mdl"
private constant integer MAXALIENFOOD = 200
endglobals
private struct s_ship
unit ship
timer t = null
player owner = null
private static method createFilter takes unit u returns boolean
return GetUnitTypeId(u)==OMEGA
endmethod
private method onCreate takes nothing returns nothing
set .t = null
set .ship = me
set .owner = GetOwningPlayer(me)
endmethod
implement AutoCreate
private method onDestroy takes nothing returns nothing
set .t = null
set .ship = null
set .owner = null
endmethod
implement AutoDestroy
endstruct
private function Update takes nothing returns nothing
local timer t = GetExpiredTimer()
local s_ship dat = GetTimerData(t)
if not (IsUnitType(dat.ship,UNIT_TYPE_DEAD)) and dat.ship!=null then
if GetPlayerState(dat.owner, PLAYER_STATE_RESOURCE_FOOD_USED)<MAXALIENFOOD then
call DestroyEffect(AddSpecialEffect(FX,GetUnitX(dat.ship),GetUnitY(dat.ship)))
call CreateUnit(dat.owner,ALPHA,GetUnitX(dat.ship),GetUnitY(dat.ship),GetUnitFacing(dat.ship))
endif
else
call ReleaseTimer(t)
endif
endfunction
private function StartProduction takes unit ship returns nothing
local s_ship dat = s_ship[ship]
set dat.ship = ship
set dat.owner = GetOwningPlayer(dat.ship)
set dat.t = NewTimer()
call SetTimerData(dat.t, dat)
call TimerStart( dat.t, TIMEOUT, true, function Update )
endfunction
private function Enter takes nothing returns boolean
local unit entering = GetTriggerUnit()
if GetUnitTypeId(entering)==OMEGA then
call Text(entering,false,"Entering the energy field of a sun")
call StartProduction(entering)
endif
set entering = null
return false
endfunction
private function StopProduction takes unit ship returns nothing
local s_ship dat = s_ship[ship]
call ReleaseTimer(dat.t)
endfunction
private function Leave takes nothing returns boolean
local unit leaving = GetTriggerUnit()
if GetUnitTypeId(leaving)==OMEGA then
call Text(leaving,false,"Leaving the energy field of a sun")
call StopProduction(leaving)
endif
set leaving = null
return false
endfunction
private struct s_star
unit star = null
trigger enter = null
trigger leave = null
rect re = null
rect rl = null
private static method createFilter takes unit u returns boolean
return GetUnitTypeId(u)==SUN
endmethod
private method onCreate takes nothing returns nothing
local real x = GetUnitX(me)
local real y = GetUnitY(me)
set .star = me
call SetUnitPathing(.star,false)
set .re = Rect(x-RANGE,y-RANGE,x+RANGE,y+RANGE)
set .rl = Rect(x-RANGE,y-RANGE,x+RANGE,y+RANGE)
set .enter = CreateTrigger()
call TriggerRegisterEnterRectSimple(.enter,.re )
call TriggerAddCondition(.enter, Condition(function Enter))
set .leave = CreateTrigger()
call TriggerRegisterLeaveRectSimple(.leave,.rl )
call TriggerAddCondition(.leave, Condition(function Leave))
endmethod
implement AutoCreate
private method onDestroy takes nothing returns nothing
call RemoveRect(.re)
call RemoveRect(.rl)
set .re = null
set .rl = null
call DisableTrigger(.enter)
call DestroyTrigger(.enter)
set .enter = null
call DisableTrigger(.leave)
call DestroyTrigger(.leave)
set .leave = null
set .star = null
endmethod
implement AutoDestroy
endstruct
endlibrary
//TESH.scrollpos=1
//TESH.alwaysfold=0
scope piratagemodules initializer init
globals
private constant string FX = "UI\\Feedback\\GoldCredit\\GoldCredit.mdl"
private constant integer SPEED = 30
private constant string C1 = "|cff008040"
private constant string C2 = "|cff80FFFF"
private constant string C = " |r"
private constant integer CHANCE = 25
private constant real TIMEOUT = 0.05
private constant integer STEAL_SPELLBOOK = 'A02V'
private constant integer PRODUCT = 'I000'
endglobals
private function GetProductAmount takes unit cargo returns integer
local integer i = 0
local item carriedItem = null
local integer carriedItemCharges = 0
loop
exitwhen i > 5
set carriedItem = UnitItemInSlot(cargo, i)
if GetItemTypeId(carriedItem) == PRODUCT then
set carriedItemCharges = GetItemCharges(carriedItem)
set carriedItem = null
return carriedItemCharges
endif
set i = i + 1
endloop
set carriedItem = null
return 0
endfunction
private function Steal takes unit pirate, unit cargo returns nothing
local integer gold = GetRandomInt(0,200)
local integer iron = GetRandomInt(0,20)
local integer i = 0
local player owner = GetOwningPlayer(pirate)
local real x = GetUnitX(pirate)
local real y = GetUnitY(pirate)
local item carriedItem = null
local integer charges = 0
loop
exitwhen i > 5
set carriedItem = UnitItemInSlot(cargo, i)
if GetItemTypeId(carriedItem) == PRODUCT then
set charges = GetItemCharges(carriedItem)
call SetItemCharges(carriedItem,0)
endif
set i = i + 1
endloop
call DestroyEffect(AddSpecialEffect(FX,x,y))
set gold = gold*charges
set iron = iron*charges
call SetResource(owner,gold,iron)
call Text(pirate,false,C1+I2S(gold)+"Pulsars"+C+" - "+C2+I2S(iron)+"Iron"+C)
set owner = null
set carriedItem = null
endfunction
private struct str
unit cargo
unit pirate
real angle
integer distance
integer i
lightning light
endstruct
private function Pull takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
local real x1 = GetUnitX(dat.cargo)
local real y1 = GetUnitY(dat.cargo)
local real z1 = GetUnitFlyHeight(dat.cargo)+10.
local real x2 = GetUnitX(dat.pirate)
local real y2 = GetUnitY(dat.pirate)
local real z2 = GetUnitFlyHeight(dat.pirate)+10.
local real newX = x1 + SPEED*Cos(dat.angle)
local real newY = y1 + SPEED*Sin(dat.angle)
if dat.i < dat.distance and GetUnitState(dat.cargo, UNIT_STATE_LIFE) > 0 and GetUnitState(dat.pirate, UNIT_STATE_LIFE) > 0 then
set dat.i = dat.i + 1
call SetUnitPosition(dat.cargo, newX, newY)
call IssueImmediateOrder(dat.pirate,"stop")
call MoveLightningEx(dat.light,true,x2, y2, z2, x1, y1, z1 )
else
call DestroyLightning(dat.light)
call UnitRemoveAbility( dat.pirate, GARN)
if dat.i >= dat.distance and GetUnitState(dat.cargo, UNIT_STATE_LIFE) > 0 and GetUnitState(dat.pirate, UNIT_STATE_LIFE) > 0 then
call Steal(dat.pirate,dat.cargo)
endif
call ReleaseTimer(t)
call dat.destroy()
endif
endfunction
private function IniPull takes unit pirate,unit cargo returns nothing
local timer t = NewTimer()
local str dat = str.create()
local real x1 = GetUnitX(dat.cargo)
local real y1 = GetUnitY(dat.cargo)
local real z1 = GetUnitFlyHeight(dat.cargo)+10.
local real x2 = GetUnitX(dat.pirate)
local real y2 = GetUnitY(dat.pirate)
local real z2 = GetUnitFlyHeight(dat.pirate)+10.
set dat.cargo = cargo
set dat.pirate = pirate
set dat.angle = Atan2((y2 -y1), (x2 - x1))
set dat.distance =R2I(SquareRoot((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))/SPEED)
set dat.i = 0
set dat.light = AddLightningEx("LEAS", true, x2, y2, z2, x1, y1, z1)
call UnitAddAbility( dat.pirate, GARN)
call SetTimerData(t, dat)
call TimerStart (t, TIMEOUT, true, function Pull )
endfunction
private function Conditions takes nothing returns boolean
local unit pirate = GetAttacker()
local player owner = GetOwningPlayer(pirate)
local unit target = GetTriggerUnit()
//If the attacker has steal spellbook and the target have products
if GetUnitAbilityLevel(pirate,STEAL_SPELLBOOK)>= 1 and IsUnitType(target,UNIT_TYPE_MECHANICAL)==false and IsUnitEnemy(pirate,GetOwningPlayer(target))==true then
call UpdateRank(owner,XP_ATTACK)
if GetRandomInt(1,100)<=CHANCE then //and GetProductAmount(target)>0 then
call UpdateRank(owner,XP_STEAL)
call IniPull(pirate,target)
endif
endif
set owner = null
set pirate = null
set target = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=49
//TESH.alwaysfold=0
library Symbiosis initializer init needs SpellEvent, TextDisplay
globals
private constant integer MAXALIENFOOD = 200
private constant integer SYMBIOSYS_SPELL = 'A047'
private constant integer CLONE = 'B00E'
private constant integer FINAL_SYMBIOSYS_SPELL = 'A04L'
private constant real FINAL_SYMBIOSYS_AOE = 400.
private constant real SYMBIOSYS_AOE = 100.
private constant string FX = "Abilities\\Spells\\Items\\ClarityPotion\\ClarityTarget.mdl"
private constant string MESSAGE = "Not enough ships to create a new one."
private integer array AlienShipId [10]
private integer array AlienShipValue [10]
private constant integer OMEGA = 'h00U'
private integer AlienShipMax = 0
private integer Amount = 0
private integer Checked = 0
private player Owner = null
private constant integer COEFF = 4
private key INDEX_VALUE
private hashtable HashT1
endglobals
//! textmacro t__SymbiosisShips_Init takes UNIT_TYPE , UNIT_VALUE
call SaveInteger(HashT1,$UNIT_TYPE$,INDEX_VALUE,$UNIT_VALUE$)
//! endtextmacro
private function SetAlienVariables takes nothing returns nothing
//Light Shuttle Alpha
set AlienShipId[1]='h00Q'
set AlienShipValue[1]= 1
//! runtextmacro t__SymbiosisShips_Init("'h00Q'","1")
//Shuttle Beta
set AlienShipId[2]='h00R'
set AlienShipValue[2]= 4
//! runtextmacro t__SymbiosisShips_Init("'h00R'","4")
//Frigate Iota
set AlienShipId[3]='h00V'
set AlienShipValue[3]= 16
//! runtextmacro t__SymbiosisShips_Init("'h00V'","16")
//Cruiser Gamma
set AlienShipId[4]='h00W'
set AlienShipValue[4]= 64
//! runtextmacro t__SymbiosisShips_Init("'h00W'","64")
//Cruiser Omega
set AlienShipId[5]='h00U'
set AlienShipValue[5]= 256
//! runtextmacro t__SymbiosisShips_Init("'h00U'","256")
//Blank
//set AlienShipId[6]='ZZZZ'
//set AlienShipValue[6]= 1024
///! runtextmacro t__SymbiosisShips_Init("'ZZZZ'","1024")
set AlienShipMax = 5
endfunction
private function ConvertUnit takes nothing returns boolean
local integer unitId = GetUnitTypeId(GetFilterUnit())
if GetOwningPlayer(GetFilterUnit())==Owner and GetUnitAbilityLevel(GetFilterUnit(),CLONE)<=0 and not(IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD)) and not(IsUnitType(GetFilterUnit(),UNIT_TYPE_HERO)) and unitId!=OMEGA then
if Checked <= Amount then
call DestroyEffect(AddSpecialEffect(FX,GetUnitX(GetFilterUnit()),GetUnitX(GetFilterUnit())))
set Checked = Checked + LoadInteger(HashT1,unitId,INDEX_VALUE)
call RemoveUnit(GetFilterUnit())
endif
endif
return true
endfunction
private function CheckUnit takes nothing returns boolean
local integer unitId = GetUnitTypeId(GetFilterUnit())
if GetOwningPlayer(GetFilterUnit())==Owner and GetUnitAbilityLevel(GetFilterUnit(),CLONE)<=0 and not(IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD)) and not(IsUnitType(GetFilterUnit(),UNIT_TYPE_HERO)) and unitId!=OMEGA then
set Amount = Amount + LoadInteger(HashT1,unitId,INDEX_VALUE)
endif
return true
endfunction
private function CastSymbiosis takes unit caster, real x, real y, real radius returns nothing
local player owner = GetOwningPlayer(caster)
local integer i = 0
local real facing = GetUnitFacing(caster)
local integer j = 0
set Owner = owner
set Amount = 0
set Checked = 0
call GroupEnumUnitsInRange(ENUM_GROUP, x,y,radius,Filter(function CheckUnit))
if Amount > 1 then
loop
exitwhen Amount <= 0
set i = 1
loop
exitwhen i > AlienShipMax
if Amount>=AlienShipValue[i] and Amount<AlienShipValue[i+1] then
call GroupEnumUnitsInRange(ENUM_GROUP, x,y,radius,Filter(function ConvertUnit))
if Amount<2*AlienShipValue[i] then
call CreateUnit(owner,AlienShipId[i],x,y,facing)
set Amount = Amount - AlienShipValue[i]
else
call CreateUnit(owner,AlienShipId[i],x,y,facing)
call CreateUnit(owner,AlienShipId[i],x,y,facing)
set Amount = Amount - 2*AlienShipValue[i]
endif
endif
set i = i + 1
endloop
set j = j + 1
endloop
else
call ErrorSound(owner)
call DisplayTextToPlayer(owner,0.,0.,MESSAGE)
endif
set owner = null
endfunction
private function SpellCast takes nothing returns nothing
if SpellEvent.AbilityId == SYMBIOSYS_SPELL then
call CastSymbiosis(SpellEvent.CastingUnit,SpellEvent.TargetX,SpellEvent.TargetY,SYMBIOSYS_AOE)
elseif SpellEvent.AbilityId == FINAL_SYMBIOSYS_SPELL then
call CastSymbiosis(SpellEvent.CastingUnit,SpellEvent.TargetX,SpellEvent.TargetY,FINAL_SYMBIOSYS_AOE)
endif
endfunction
private function init takes nothing returns nothing
set HashT1 = InitHashtable()
call SetAlienVariables()
call RegisterSpellFinishResponse(SYMBIOSYS_SPELL,SpellCast)
call RegisterSpellFinishResponse(FINAL_SYMBIOSYS_SPELL,SpellCast)
endfunction
endlibrary
//TESH.scrollpos=28
//TESH.alwaysfold=0
scope timewarp initializer init
globals
private constant integer SPELL = 'A01G'
private constant integer DUMMYID = 'o00H'
private constant real DUR = 20.
private constant real RADIUS = 150.
private constant real ANGLE = 12.
private constant integer COUNT = 30
endglobals
private struct str
lightning array light [COUNT]
endstruct
private function Wait takes nothing returns nothing
local timer t = GetExpiredTimer()
local str dat = GetTimerData(t)
local integer i = 0
loop
set i = i + 1
exitwhen i > COUNT
call DestroyLightning(dat.light[i])
set dat.light[i]= null
endloop
call ReleaseTimer(t)
call dat.destroy()
endfunction
private function Actions takes nothing returns nothing
local integer i = 0
local timer t = NewTimer()
local str dat = str.create()
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
local real x1 = 0.
local real y1 = 0.
local real x2 = 0.
local real y2 = 0.
call UnitApplyTimedLife(CreateUnit(owner,DUMMYID,SpellEvent.TargetX,SpellEvent.TargetY,0.),'BTLF',DUR)
loop
set i = i + 1
exitwhen i > COUNT
set x1 = SpellEvent.TargetX + RADIUS * Cos(i * ANGLE *bj_DEGTORAD)
set y1 = SpellEvent.TargetY + RADIUS * Sin(i * ANGLE *bj_DEGTORAD)
set x2 = SpellEvent.TargetX + RADIUS * Cos(((i * ANGLE)-ANGLE) *bj_DEGTORAD)
set y2 = SpellEvent.TargetY + RADIUS * Sin(((i * ANGLE)-ANGLE) *bj_DEGTORAD)
set dat.light[i] = AddLightning("DRAM",true,x1,y1,x2,y2)
endloop
call SetTimerData(t, dat)
call TimerStart (t,DUR,false,function Wait )
set owner = null
endfunction
public function init takes nothing returns nothing
call RegisterSpellFinishResponse(SPELL,Actions)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope toxfield initializer init
globals
private constant integer SPELL = 'A03C'
private constant integer DUMMYID = 'o013'
private constant integer RESEARCH = 'R00U'
private constant integer DUMMYSPELL = 'A042'
endglobals
private function Actions takes nothing returns nothing
local player owner = GetOwningPlayer(SpellEvent.CastingUnit)
local real x = GetUnitX(SpellEvent.CastingUnit)
local real y = GetUnitY(SpellEvent.CastingUnit)
local unit dummy = CreateUnit(owner,DUMMYID,x,y,0.)
call SetUnitAbilityLevel(dummy,DUMMYSPELL,GetPlayerTechCount(owner, RESEARCH, true))
call IssuePointOrder(dummy,"acidbomb",x,y)
call UnitApplyTimedLife(dummy,'BTLF',1.)
set dummy = null
set owner = null
endfunction
public function init takes nothing returns nothing
call RegisterSpellFinishResponse(SPELL,Actions)
endfunction
endscope
//TESH.scrollpos=99
//TESH.alwaysfold=0
library BoardSystem initializer init needs AbilityPreload
globals
//Board Variables
private constant string TITLE = "|c00AAAAFFStars|r - Clan Leader Experience"
private constant real TIME = 12.
constant integer XP_ASSIMILATION = 100//Alien xp: assimilation + 100
constant integer XP_TRADE = 2//Merchant xp: trade +2 per traject, research + 10
constant integer XP_RESEARCH = 10
constant integer XP_INVASION = 100//Military: invasion + 100, research + 10
constant integer XP_STEAL = 10//Pirate xp: merchant unit steal + 10,merchant attack + 1
constant integer XP_ATTACK = 1
constant integer XP_DEATH = 5//Terrorist xp: death + 5
leaderboard Board
//Ranks Variables
integer RankMax
integer array RankReq [50]
string array RankName [50]
string array PlayerRankName [12]
integer array PlayerRankInteger [12]
constant integer RANKDUMMYID = 'o012'
constant integer RANKSPEED = 'S001'
constant integer RANKDAMAGE = 'A00A'
unit array RankDummy [12]
endglobals
private function SetRanksVariables takes nothing returns nothing
local integer i = 0
set RankReq[i]= 0
set RankName[i]="Unknown"
// ***
set i = i + 1
set RankReq[i]= 100
set RankName[i]="Stowaway"
// ***
set i = i + 1
set RankReq[i]= 1000
set RankName[i]="Passenger"
// ***
set i = i + 1
set RankReq[i]= 2000
set RankName[i]="Crew Member"
// ***
set i = i + 1
set RankReq[i]= 3000
set RankName[i]="Petty Officer Third Class"
// ***
set i = i + 1
set RankReq[i]= 4000
set RankName[i]="Petty Officer Second Class"
// ***
set i = i + 1
set RankReq[i]= 6000
set RankName[i]="Petty Officer First Class"
// ***
set i = i + 1
set RankReq[i]= 8000
set RankName[i]="Chief Petty Officer"
// ***
set i = i + 1
set RankReq[i]= 10000
set RankName[i]="Senior Chief Petty Officer"
// ***
set i = i + 1
set RankReq[i]= 12000
set RankName[i]="Master Chief Petty Officer"
// ***
set i = i + 1
set RankReq[i]= 14000
set RankName[i]="Fleet Master Chief Petty Officer"
// ***
set i = i + 1
set RankReq[i]= 16000
set RankName[i]="Master Chief Petty Officer of the Navy"
// ***
set i = i + 1
set RankReq[i]= 18000
set RankName[i]="Midshipman"
// ***
set i = i + 1
set RankReq[i]= 20000
set RankName[i]="Ensign"
// ***
set i = i + 1
set RankReq[i]= 25000
set RankName[i]="Junior GradeLieutenant"
// ***
set i = i + 1
set RankReq[i]= 30000
set RankName[i]="Lieutenant"
// ***
set i = i + 1
set RankReq[i]= 35000
set RankName[i]="Lieutenant Commander"
// ***
set i = i + 1
set RankReq[i]= 40000
set RankName[i]="Commander"
// ***
set i = i + 1
set RankReq[i]= 50000
set RankName[i]="Squad Commander"
// ***
set i = i + 1
set RankReq[i]= 60000
set RankName[i]="Fleet Commander"
// ***
set i = i + 1
set RankReq[i]= 70000
set RankName[i]="Captain"
// ***
set i = i + 1
set RankReq[i]= 80000
set RankName[i]="Squad Captain"
// ***
set i = i + 1
set RankReq[i]= 90000
set RankName[i]="Fleet Captain"
// ***
set i = i + 1
set RankReq[i]= 100000
set RankName[i]="Major"
// ***
set i = i + 1
set RankReq[i]= 120000
set RankName[i]="Colonel"
// ***
set i = i + 1
set RankReq[i]= 140000
set RankName[i]="General"
// ***
set i = i + 1
set RankReq[i]= 160000
set RankName[i]="Fleet General"
// ***
set i = i + 1
set RankReq[i]= 180000
set RankName[i]="Commodore"
// ***
set i = i + 1
set RankReq[i]= 200000
set RankName[i]="Rear Admiral"
// ***
set i = i + 1
set RankReq[i]= 250000
set RankName[i]="Vice Admiral"
// ***
set i = i + 1
set RankReq[i]= 300000
set RankName[i]="Admiral"
// ***
set i = i + 1
set RankReq[i]= 350000
set RankName[i]="Fleet Admiral"
// ***
set i = i + 1
set RankReq[i]= 400000
set RankName[i]="System Leader"
// ***
set i = i + 1
set RankReq[i]= 450000
set RankName[i]="Sector Leader"
// ***
set i = i + 1
set RankReq[i]= 500000
set RankName[i]="Cluster Leader"
// ***
set i = i + 1
set RankReq[i]= 550000
set RankName[i]="Galaxy Leader"
// ***
set i = i + 1
set RankReq[i]= 600000
set RankName[i]="Star Cluster Leader"
// ***
set i = i + 1
set RankReq[i]= 650000
set RankName[i]="Secretary"
// ***
set i = i + 1
set RankReq[i]= 700000
set RankName[i]="Adviser"
// ***
set i = i + 1
set RankReq[i]= 800000
set RankName[i]="High Adviser"
// ***
set i = i + 1
set RankReq[i]= 900000
set RankName[i]="Minister"
// ***
set i = i + 1
set RankReq[i]= 1000000
set RankName[i]="Prime Minister"
// ***
set i = i + 1
set RankReq[i]= 1500000
set RankName[i]="Imperator"
// ***
set RankMax = i
endfunction
function UpdateRank takes player whichPlayer,integer whichXp returns nothing
local integer i = GetPlayerId(whichPlayer)
local integer j = PlayerRankInteger[i]
set PlayerRankInteger[i]=PlayerRankInteger[i]+whichXp
loop
exitwhen j > RankMax
if PlayerRankInteger[i]>= RankReq[j] and PlayerRankInteger[i]<RankReq[j+1] then
if j != PlayerRankInteger[i] then
set PlayerRankName[i] = RankName[j]
call SetUnitAbilityLevel(RankDummy[i],RANKSPEED,j)
call SetUnitAbilityLevel(RankDummy[i],RANKDAMAGE,j)
call SetPlayerHandicap(whichPlayer,1.00+(j/100))
endif
endif
set j = j + 1
endloop
call LeaderboardSetItemLabel(Board,LeaderboardGetPlayerIndex(Board,whichPlayer),PlayerRankName[i]+" "+GetPlayerName(whichPlayer))
call LeaderboardSetItemValue(Board,LeaderboardGetPlayerIndex(Board,whichPlayer),PlayerRankInteger[i])
call LeaderboardSortItemsBJ(Board,bj_SORTTYPE_SORTBYVALUE,false)
endfunction
function InitializeBoard takes nothing returns nothing
local integer i = 0
set Board = CreateLeaderboardBJ(bj_FORCE_ALL_PLAYERS, TITLE )
loop
exitwhen i > MAXPLAYER
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
call LeaderboardAddItemBJ( Player(i),Board,PlayerRankName[i]+" "+GetPlayerName(Player(i)), 0 )
call LeaderboardSetItemStyle(Board,LeaderboardGetPlayerIndex(Board,Player(i)),true,true,false)
endif
set i = i + 1
endloop
endfunction
private function init takes nothing returns nothing
local integer i = 0
call SetRanksVariables()
call AbilityPreload(RANKSPEED)
call AbilityPreload(RANKDAMAGE)
loop
exitwhen i > MAXPLAYER
set PlayerRankName[i] = RankName[0]
set PlayerRankInteger[i] = 0
set i = i + 1
endloop
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope researchaddpoints initializer init
private function Conditions takes nothing returns boolean
local player owner = GetOwningPlayer(GetTriggerUnit())
local integer ownerId = GetPlayerId(owner)
if Military[ownerId]==true or Merchant[ownerId]==true then
call UpdateRank(owner,XP_RESEARCH)
endif
set owner = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_RESEARCH_FINISH )
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Test initializer RunTests
function interface proposition takes nothing returns boolean
public function Closeto takes real x, real y returns boolean
return RAbsBJ(x - y) <= 0.001
endfunction
private function prop_Closeto takes nothing returns boolean
return Closeto(1,1) and Closeto(1,1.0005) and not Closeto(0,1)
endfunction
public function DebugMsg takes string s returns nothing
call BJDebugMsg(s)
call Cheat("DebugMsg: "+s)
endfunction
public function Assert takes string name, proposition t returns nothing
if t.evaluate() then
call BJDebugMsg("|cff00ff00"+"OK "+"|r"+name)
call Cheat("DebugMsg: OK "+name)
else
call DebugMsg("|cffff0000"+"Failed "+"|r"+name)
call Cheat("DebugMsg: Failed "+name)
endif
endfunction
private function RunTests takes nothing returns nothing
debug local string n = "SelfTest "
debug call Test_Assert(n+"Closeto",proposition.prop_Closeto)
endfunction
endlibrary
//===========================================================================
function InitTrig_test_lib takes nothing returns nothing
endfunction
//TESH.scrollpos=229
//TESH.alwaysfold=0
library BigNum initializer RunTests requires Test
//prefer algebraic approach because of real subtraction issues
function log takes real y, real base returns real
local real x
local real factor = 1.0
local real logy = 0.0
local real sign = 1.0
if(y < 0.) then
return 0.0
endif
if(y < 1.) then
set y = 1.0/y
set sign = -1.0
endif
//Chop out powers of the base
loop
exitwhen y < 1.0001 //decrease this ( bounded below by 1) to improve precision
if(y > base) then
set y = y / base
set logy = logy + factor
else
set base = SquareRoot(base) //If you use just one base a lot, precompute its squareroots
set factor = factor / 2.
endif
endloop
return sign*logy
endfunction
private function prop_Log takes nothing returns boolean
if not Test_Closeto(log(10,10),1) then
return false
elseif not Test_Closeto(log(10,2.7182818),2.302585) then
return false
elseif not Test_Closeto(log(0.5,10),-0.30103) then
return false
endif
return true
endfunction
struct BigNum_l
integer leaf
BigNum_l next
debug static integer nalloc = 0
static method create takes nothing returns BigNum_l
local BigNum_l bl = BigNum_l.allocate()
set bl.next = 0
set bl.leaf = 0
debug set BigNum_l.nalloc = BigNum_l.nalloc + 1
return bl
endmethod
method onDestroy takes nothing returns nothing
debug set BigNum_l.nalloc = BigNum_l.nalloc - 1
endmethod
//true: want destroy
method Clean takes nothing returns boolean
if .next == 0 and .leaf == 0 then
return true
elseif .next != 0 and .next.Clean() then
call .next.destroy()
set .next = 0
return .leaf == 0
else
return false
endif
endmethod
method DivSmall takes integer base, integer denom returns integer
local integer quotient
local integer remainder = 0
local integer num
if .next != 0 then
set remainder = .next.DivSmall(base,denom)
endif
set num = .leaf + remainder*base
set quotient = num/denom
set remainder = num - quotient*denom
set .leaf = quotient
return remainder
endmethod
endstruct
struct BigNum
BigNum_l list
integer base
static method create takes integer base returns BigNum
local BigNum b = BigNum.allocate()
set b.list = 0
set b.base = base
return b
endmethod
method onDestroy takes nothing returns nothing
local BigNum_l cur = .list
local BigNum_l next
loop
exitwhen cur == 0
set next = cur.next
call cur.destroy()
set cur = next
endloop
endmethod
method IsZero takes nothing returns boolean
local BigNum_l cur = .list
loop
exitwhen cur == 0
if cur.leaf != 0 then
return false
endif
set cur = cur.next
endloop
return true
endmethod
method Dump takes nothing returns nothing
local BigNum_l cur
local string s = ""
loop
exitwhen cur == 0
set s = I2S(cur.leaf)+" "+s
set cur = cur.next
endloop
call BJDebugMsg(s)
endmethod
method Clean takes nothing returns nothing
local BigNum_l cur = .list
call cur.Clean()
endmethod
//fails if bignum is null
//BASE() + carry must be less than MAXINT()
method AddSmall takes integer carry returns nothing
local BigNum_l next
local BigNum_l cur = .list
local integer sum
if cur == 0 then
set cur = BigNum_l.create()
set .list = cur
endif
loop
exitwhen carry == 0
set sum = cur.leaf + carry
set carry = sum / .base
set sum = sum - carry*.base
set cur.leaf = sum
if cur.next == 0 then
set cur.next = BigNum_l.create()
endif
set cur = cur.next
endloop
endmethod
//x*BASE() must be less than MAXINT()
method MulSmall takes integer x returns nothing
local BigNum_l cur = .list
local integer product
local integer remainder
local integer carry = 0
loop
exitwhen cur == 0 and carry == 0
set product = x * cur.leaf + carry
set carry = product/.base
set remainder = product - carry*.base
set cur.leaf = remainder
if cur.next == 0 and carry != 0 then
set cur.next = BigNum_l.create()
endif
set cur = cur.next
endloop
endmethod
//Returns remainder
method DivSmall takes integer denom returns integer
return .list.DivSmall(.base,denom)
endmethod
method LastDigit takes nothing returns integer
local BigNum_l cur = .list
local BigNum_l next
loop
set next = cur.next
exitwhen next == 0
set cur = next
endloop
return cur.leaf
endmethod
endstruct
private function prop_Allocator1 takes nothing returns boolean
local BigNum b1
local BigNum b2
set b1 = BigNum.create(37)
call b1.destroy()
set b2 = BigNum.create(37)
call b2.destroy()
return b1 == b2
endfunction
private function prop_Allocator2 takes nothing returns boolean
local BigNum b1
local boolean b = false
set b1 = BigNum.create(37)
call b1.AddSmall(17)
call b1.MulSmall(19)
debug if BigNum_l.nalloc < 1 then
debug return false
debug endif
call b1.destroy()
debug set b = BigNum_l.nalloc == 0
return b
endfunction
private function prop_Arith takes nothing returns boolean
local BigNum b1
set b1 = BigNum.create(37)
call b1.AddSmall(73)
call b1.MulSmall(39)
call b1.AddSmall(17)
//n = 2864
if b1.DivSmall(100) != 64 then
return false
elseif b1.DivSmall(7) != 0 then
return false
elseif b1.IsZero() then
return false
elseif b1.DivSmall(3) != 1 then
return false
elseif b1.DivSmall(3) != 1 then
return false
elseif not b1.IsZero() then
return false
endif
return true
endfunction
private function RunTests takes nothing returns nothing
debug local string n = "BigNum "
debug call Test_Assert(n+"Log",proposition.prop_Log)
debug call Test_Assert(n+"Allocator1",proposition.prop_Allocator1)
debug call Test_Assert(n+"Allocator2",proposition.prop_Allocator2)
debug call Test_Assert(n+"Arithmetic",proposition.prop_Arith)
endfunction
endlibrary
//===========================================================================
function InitTrig_bignum_lib takes nothing returns nothing
endfunction
//TESH.scrollpos=9
//TESH.alwaysfold=0
library Savecode initializer RunTests requires BigNum
//library Savecode requires BigNum
//Colorize colors
constant function uppercolor takes nothing returns string
return "|c00FFFFFF"
endfunction
constant function lowercolor takes nothing returns string
return "|c00AAAAFF"
endfunction
constant function numcolor takes nothing returns string
return "|c0000AA00"
endfunction
private function player_charset takes nothing returns string
return "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
endfunction
private function player_charsetlen takes nothing returns integer
return StringLength(player_charset())
endfunction
private function charset takes nothing returns string
return "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
// return "0123456789"
endfunction
private function charsetlen takes nothing returns integer
return StringLength(charset())
endfunction
private function BASE takes nothing returns integer
return charsetlen()
endfunction
private constant function HASHN takes nothing returns integer
return 5000 //1./HASHN() is the probability of a random code being valid
endfunction
private constant function MAXINT takes nothing returns integer
return 2147483647
endfunction
private function player_chartoi takes string c returns integer
local integer i = 0
local string cs = player_charset()
local integer len = player_charsetlen()
loop
exitwhen i>=len or c == SubString(cs,i,i+1)
set i = i + 1
endloop
return i
endfunction
private function chartoi takes string c returns integer
local integer i = 0
local string cs = charset()
local integer len = charsetlen()
loop
exitwhen i>=len or c == SubString(cs,i,i+1)
set i = i + 1
endloop
return i
endfunction
private function itochar takes integer i returns string
return SubString(charset(),i,i+1)
endfunction
//You probably want to use a different char set for this
//Also, use a hash that doesn't suck so much
private function scommhash takes string s returns integer
local integer array count
local integer i = 0
local integer len = StringLength(s)
local integer x
set s = StringCase(s,true)
loop
exitwhen i >= len
set x = player_chartoi(SubString(s,i,i+1))
set count[x] = count[x] + 1
set i = i + 1
endloop
set i = 0
set len = player_charsetlen()
set x = 0
loop
exitwhen i>= len
set x = count[i]*count[i]*i+count[i]*x+x+199
// call BJDebugMsg(I2S(x)+" "+I2S(count[i]))
// call TriggerSleepAction(0.)
set i = i + 1
endloop
if x < 0 then
set x = -x
endif
return x
endfunction
private function modb takes integer x returns integer
if x >= BASE() then
return x - BASE()
elseif x < 0 then
return x + BASE()
else
return x
endif
endfunction
struct Savecode
real digits //logarithmic approximation
BigNum bignum
static method create takes nothing returns Savecode
local Savecode sc = Savecode.allocate()
set sc.digits = 0.
set sc.bignum = BigNum.create(BASE())
return sc
endmethod
method onDestroy takes nothing returns nothing
call .bignum.destroy()
endmethod
method Encode takes integer val, integer max returns nothing
set .digits = .digits + log(max+1,BASE())
call .bignum.MulSmall(max+1)
call .bignum.AddSmall(val)
endmethod
method Decode takes integer max returns integer
return .bignum.DivSmall(max+1)
endmethod
method IsEmpty takes nothing returns boolean
return .bignum.IsZero()
endmethod
method Length takes nothing returns real
return .digits
endmethod
method Clean takes nothing returns nothing
call .bignum.Clean()
endmethod
//These functions get too intimate with BigNum_l
method Pad takes nothing returns nothing
local BigNum_l cur = .bignum.list
local BigNum_l prev
local integer maxlen = R2I(1.0 + .Length())
loop
exitwhen cur == 0
set prev = cur
set cur = cur.next
set maxlen = maxlen - 1
endloop
loop
exitwhen maxlen <= 0
set prev.next = BigNum_l.create()
set prev = prev.next
set maxlen = maxlen - 1
endloop
endmethod
method ToString takes nothing returns string
local BigNum_l cur = .bignum.list
local string s = ""
loop
exitwhen cur == 0
set s = itochar(cur.leaf) + s
set cur = cur.next
endloop
return s
endmethod
method FromString takes string s returns nothing
local integer i = StringLength(s)-1
local BigNum_l cur = BigNum_l.create()
set .bignum.list = cur
loop
set cur.leaf = chartoi(SubString(s,i,i+1))
exitwhen i <= 0
set cur.next = BigNum_l.create()
set cur = cur.next
set i = i - 1
endloop
endmethod
method Hash takes nothing returns integer
local integer hash = 0
local integer x
local BigNum_l cur = .bignum.list
loop
exitwhen cur == 0
set x = cur.leaf
set hash = ModuloInteger(hash+79*hash/(x+1) + 293*x/(1+hash - (hash/BASE())*BASE()) + 479,HASHN())
set cur = cur.next
endloop
return hash
endmethod
//this is not cryptographic which is fine for this application
//sign = 1 is forward
//sign = -1 is backward
method Obfuscate takes integer key, integer sign returns nothing
local integer seed = GetRandomInt(0,MAXINT())
local integer advance
local integer x
local BigNum_l cur = .bignum.list
if sign == -1 then
call SetRandomSeed(.bignum.LastDigit())
set cur.leaf = modb(cur.leaf + sign*GetRandomInt(0,BASE()-1))
set x = cur.leaf
endif
call SetRandomSeed(key)
loop
exitwhen cur == 0
if sign == -1 then
set advance = cur.leaf
endif
set cur.leaf = modb(cur.leaf + sign*GetRandomInt(0,BASE()-1))
if sign == 1 then
set advance = cur.leaf
endif
set advance = advance + GetRandomInt(0,BASE()-1)
call SetRandomSeed(advance)
set x = cur.leaf
set cur = cur.next
endloop
if sign == 1 then
call SetRandomSeed(x)
set .bignum.list.leaf = modb(.bignum.list.leaf + sign*GetRandomInt(0,BASE()-1))
endif
call SetRandomSeed(seed)
endmethod
method Dump takes nothing returns nothing
local BigNum_l cur = .bignum.list
local string s = ""
set s = "max: "+R2S(.digits)
loop
exitwhen cur == 0
set s = I2S(cur.leaf)+" "+s
set cur = cur.next
endloop
//call BJDebugMsg(s)
endmethod
method Save takes player p, integer loadtype returns string
local integer key = scommhash(GetPlayerName(p))+loadtype*73
local string s
local integer hash
call .Clean()
set hash = .Hash()
call .Encode(hash,HASHN())
call .Clean()
/////////////////////// Save code information. Comment out next two lines in implementation
//call BJDebugMsg("Expected length: " +I2S(R2I(1.0+.Length())))
//call BJDebugMsg("Room left in last char: "+R2S(1.-ModuloReal((.Length()),1)))
///////////////////////
call .Pad()
call .Obfuscate(key,1)
return .ToString()
endmethod
method Load takes player p, string s, integer loadtype returns boolean
local integer ikey = scommhash(GetPlayerName(p))+loadtype*73
local integer inputhash
call .FromString(s)
call .Obfuscate(ikey,-1)
set inputhash = .Decode(HASHN())
call .Clean()
return inputhash == .Hash()
endmethod
endstruct
private function isupper takes string c returns boolean
return c == StringCase(c,true)
endfunction
private function ischar takes string c returns boolean
return S2I(c) == 0 and c!= "0"
endfunction
private function chartype takes string c returns integer
if(ischar(c)) then
if isupper(c) then
return 0
else
return 1
endif
else
return 2
endif
endfunction
private function testchar takes string c returns nothing
if(ischar(c)) then
if isupper(c) then
//call BJDebugMsg(c+" isupper")
else
//call BJDebugMsg(c+" islower")
endif
else
//call BJDebugMsg(c+ " isnumber")
endif
endfunction
public function colorize takes string s returns string
local string out = ""
local integer i = 0
local integer len = StringLength(s)
local integer ctype
local string c
loop
exitwhen i >= len
set c = SubString(s,i,i+1)
set ctype = chartype(c)
if ctype == 0 then
set out = out + uppercolor()+c+"|r"
elseif ctype == 1 then
set out = out + lowercolor()+c+"|r"
else
set out = out + numcolor()+c+"|r"
endif
set i = i + 1
endloop
return out
endfunction
private function prop_Savecode takes nothing returns boolean
local string s
local Savecode loadcode
//--- Data you want to save ---
local integer medal1 = 10
local integer medal2 = 3
local integer medalmax = 13
local integer XP = 1337
local integer XPmax = 1000000
local Savecode savecode = Savecode.create()
//call SetPlayerName(Player(0),"yomp")
//call SetPlayerName(Player(1),"fruitcup")
call savecode.Encode(medal1,medalmax)
call savecode.Encode(medal2,medalmax)
call savecode.Encode(XP,XPmax)
//--- Savecode_save generates the savecode for a specific player ---
set s = savecode.Save(Player(0),1)
call savecode.destroy()
// call BJDebugMsg("Savecode: " + Savecode_colorize(s))
//--- User writes down code, inputs again ---
set loadcode = Savecode.create()
if loadcode.Load(Player(0),s,1) then
// call BJDebugMsg("load ok")
else
//call BJDebugMsg("load failed")
return false
endif
//Must decode in reverse order of encodes
// load object : max value that data can take
if XP != loadcode.Decode(XPmax) then
return false
elseif medal2 != loadcode.Decode(medalmax) then
return false
elseif medal1 != loadcode.Decode(medalmax) then
return false
endif
call loadcode.destroy()
return true
endfunction
private function RunTests takes nothing returns nothing
debug local string s = "Savecode "
debug call Test_Assert(s+"first",proposition.prop_Savecode)
debug call Test_Assert(s+"second",proposition.prop_Savecode)
endfunction
endlibrary
//===========================================================================
function InitTrig_SL_save_system takes nothing returns nothing
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope saverun initializer init
private function Conditions takes nothing returns boolean
local Savecode savecode = Savecode.create()
local player whichPlayer = GetTriggerPlayer()
local integer whichPlayerId = GetPlayerId(whichPlayer)
local string text = null
if PlayerSave[whichPlayerId] > 0 then
call savecode.Encode(PlayerRankInteger[whichPlayerId],CODEMAXRANK)
call savecode.Encode(StringLength(GetPlayerName(whichPlayer)),CODEMAXLETTER)
set text = savecode.Save(whichPlayer,1)
set text= Savecode_colorize(text)
call DisplayTimedTextToPlayer(whichPlayer,0.00,0.00,30.00,"-load " + text)
call savecode.destroy()
set PlayerSave[whichPlayerId]=PlayerSave[whichPlayerId]-1
call DisplayTimedTextToPlayer(whichPlayer,0.00,0.00,30.00,I2S(PlayerSave[whichPlayerId])+" saves remaining")
else
call ErrorSound(whichPlayer)
call DisplayTextToPlayer(whichPlayer,0.00,0.00,"You already saved 3 times")
endif
set whichPlayer = null
set text = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
exitwhen i > MAXPLAYER
call TriggerRegisterPlayerChatEvent( t, Player(i), "-save", false )
set i = i + 1
endloop
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope
//TESH.scrollpos=15
//TESH.alwaysfold=0
scope loadrun initializer init
globals
constant integer CODEMAXRANK = 2000000
constant integer CODEMAXLETTER = 30
integer array PlayerPoints [9]
boolean array PlayerLoad [9]
integer array PlayerSave [9]
endglobals
private function Conditions takes nothing returns boolean
local Savecode loadcode
local player whichPlayer = GetTriggerPlayer()
local integer whichPlayerId = GetPlayerId(whichPlayer)
local string text = GetEventPlayerChatString()
local integer textSize = StringLength(text)
local integer nameSize = 0
local integer rank = 0
set text = SubString(text,6,textSize)
set loadcode = Savecode.create()
if PlayerLoad[whichPlayerId]==false then
if loadcode.Load(whichPlayer,text,1) then
set nameSize = loadcode.Decode(CODEMAXLETTER)
set rank = loadcode.Decode(CODEMAXRANK)
if nameSize == StringLength(GetPlayerName(whichPlayer)) then
set PlayerRankInteger[whichPlayerId] = rank
call DisplayTextToPlayer(whichPlayer,0.00,0.00,"Load Code Correct")
call UpdateRank(whichPlayer,0)
else
call ErrorSound(whichPlayer)
call DisplayTextToPlayer(whichPlayer,0.00,0.00,"You are not the player associated with this code")
endif
else
call ErrorSound(whichPlayer)
call DisplayTextToPlayer(whichPlayer,0.00,0.00,"Load code Incorrect")
endif
else
call ErrorSound(whichPlayer)
call DisplayTextToPlayer(whichPlayer,0.00,0.00,"You already have loaded a code")
endif
call loadcode.destroy()
set whichPlayer = null
set text = null
return false
endfunction
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
exitwhen i > MAXPLAYER
set PlayerSave[i] = 3
set PlayerLoad[i] = false
call TriggerRegisterPlayerChatEvent( t, Player(i), "-load", false )
set i = i + 1
endloop
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endscope