//==========================================================================================
// Bombardment v1.00 by watermelon_1234
//******************************************************************************************
// Libraries required: (Libraries with * are optional)
// - GroupUtils
// - SpellEvent
// - xemissile
//##########################################################################################
// Importing:
// 1. Copy the ability, Bombardment
// 2. Implement the required libraries
// 3. Copy this trigger
// 4. Configure the spell
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Notes:
// - Configuration can be pretty messy. I suggest configuring each cannon's settings
// separately and testing a lot to make sure nothing is off.
// - The directions I refer to are all from the perspective of a person standing at the
// front of the ship.
//==========================================================================================
scope Bombardment initializer Init
//==========================================================================================
// CONSTANTS
//==========================================================================================
globals
//------------------------------------------------------------------------------------------
// General spell settings
//------------------------------------------------------------------------------------------
private constant integer SPELL_ID = 'A004' // Raw id of the Bombardment ability
private constant attacktype ATK_TYPE = ATTACK_TYPE_CHAOS // Attack type
private constant damagetype DMG_TYPE = DAMAGE_TYPE_UNIVERSAL // Damage type
private constant weapontype WPN_TYPE = null // Weapon type
//------------------------------------------------------------------------------------------
// General cannonball settings
//------------------------------------------------------------------------------------------
private constant string CANNONBALL_SFX = "war3mapImported\\SuperpultProjectile.mdl" // Path of the cannonball sfx
private constant real CANNONBALL_LAND_HEIGHT = 0. // Height at which the cannonball lands
//------------------------------------------------------------------------------------------
// Big cannon settings
//------------------------------------------------------------------------------------------
private constant real BIG_CANNON_SCALE = 1.75 // Scaling of the cannonball
private constant real BIG_CANNON_AOE = 250. // AoE of the cannonball's damage
private constant real BIG_CANNON_HEIGHT = 75. // Initial height of the cannonball
private constant real BIG_CANNON_HORI_OFFSET = -10 // Horizontal offset from the ship's coordinates
private constant real BIG_CANNON_VERT_OFFSET = 145. // Vertical offset from the ship's coordinates
private constant real BIG_CANNON_ARC = 0.04 // Arc of missile
//------------------------------------------------------------------------------------------
// Medium cannon settings
//------------------------------------------------------------------------------------------
private constant real MED_CANNON_SCALE = 1.25 // Scaling of the cannonball
private constant real MED_CANNON_AOE = 175. // AoE of the cannonball's damage
private constant real MED_CANNON_HEIGHT = 75. // Initial height of the cannonball
private constant real MED_CANNON_HORI_OFFSET = 30 // Horizontal offset from the ship's coordinates
private constant real MED_CANNON_VERT_OFFSET = 125. // Vertical offset from the ship's coordinates
private constant real MED_CANNON_FIX_OFFSET = 35. // Offset correction since the juggernaut isn't symmetrically divided at its coordinates
private constant real MED_ANG_OFFSET = bj_PI/10 // The angle at which the cannonballs are shot at
private constant real MED_CANNON_ARC = 0.08 // Arc of missile
//------------------------------------------------------------------------------------------
// Small cannon settings
//------------------------------------------------------------------------------------------
private constant real SMA_CANNON_SCALE = .75 // Scaling of the cannonball
private constant real SMA_CANNON_AOE = 125. // AoE of the cannonball's damage
private constant real SMA_CANNON_HEIGHT = 115. // Initial height of the cannonball
private constant real SMA_CANNON_HORI_OFFSET = 10. // Horizontal offset from the ship's coordinates
private constant real SMA_CANNON_VERT_OFFSET = 65. // Vertical offset from the ship's coordinates
private constant real SMA_CANNON_FIX_OFFSET = 25. // Offset correction since the juggernaut isn't symmetrically divided at its coordinates
private constant real SMA_CANNON_ARC = 0.1 // Arc of missile
endglobals
//==========================================================================================
// OTHER CONFIGURATION
//==========================================================================================
// Units that will be damaged by the spell
private function AffectedTargets takes unit target, player owner returns boolean
return not IsUnitType(target, UNIT_TYPE_DEAD) and /*
*/ IsUnitEnemy(target, owner) and /*
*/ not IsUnitType(target, UNIT_TYPE_FLYING)
endfunction
// Speed of cannonball from big cannon
private constant function BigCannonSpeed takes integer lvl returns real
return 650.
endfunction
// Distance travelled of the cannonball shot from big cannon
private constant function BigCannonDistance takes integer lvl returns real
return 400.
endfunction
// Damage dealt by the big cannonball
private constant function BigCannonDamage takes integer lvl returns real
return 100.
endfunction
// Speed of cannonball from medium cannon
private constant function MediumCannonSpeed takes integer lvl returns real
return 850.
endfunction
// Distance travelled of the cannonball shot from medium cannon
private constant function MediumCannonDistance takes integer lvl returns real
return 500.
endfunction
// Damage dealt by the medium cannonball
private constant function MediumCannonDamage takes integer lvl returns real
return 65.
endfunction
// Speed of cannonball from small cannon
private constant function SmallCannonSpeed takes integer lvl returns real
return 1150.
endfunction
// Distance travelled of the cannonball shot from small cannon
private constant function SmallCannonDistance takes integer lvl returns real
return 600.
endfunction
// Damage dealt by the small cannonball
private constant function SmallCannonDamage takes integer lvl returns real
return 30.
endfunction
//==========================================================================================
// END OF CONFIGURATION
//==========================================================================================
private struct missile extends xemissile
unit cast
integer lvl
integer s // Used to decide the scale of the cannon ball
method onHit takes nothing returns nothing
local real area
local real dmg
local unit u
// Big cannon
if .s == 0 then
set area = BIG_CANNON_AOE
set dmg = BigCannonDamage(.lvl)
// Medium cannon
elseif .s == 1 then
set area = MED_CANNON_AOE
set dmg = MediumCannonDamage(.lvl)
// Small cannon
else
set area = SMA_CANNON_AOE
set dmg = SmallCannonDamage(.lvl)
endif
call GroupEnumUnitsInArea(ENUM_GROUP, .x, .y, area, null)
loop
set u = FirstOfGroup(ENUM_GROUP)
exitwhen u == null
call GroupRemoveUnit(ENUM_GROUP, u)
if AffectedTargets(u, GetOwningPlayer(.cast)) then
call UnitDamageTarget(.cast, u, dmg, false, true, ATK_TYPE, DMG_TYPE, WPN_TYPE)
endif
endloop
endmethod
static method create takes unit c, integer lvl, real x, real y, real tx, real ty, integer s returns thistype
local real height
local real scale
local real speed
local real arc
local thistype this
// Big cannon
if s == 0 then
set height = BIG_CANNON_HEIGHT
set scale = BIG_CANNON_SCALE
set speed = BigCannonSpeed(lvl)
set arc = BIG_CANNON_ARC
// Medium cannon
elseif s == 1 then
set height = MED_CANNON_HEIGHT
set scale = MED_CANNON_SCALE
set speed = MediumCannonSpeed(lvl)
set arc = MED_CANNON_ARC
// Small cannon
else
set height = SMA_CANNON_HEIGHT
set scale = SMA_CANNON_SCALE
set speed = SmallCannonSpeed(lvl)
set arc = SMA_CANNON_ARC
endif
set this = thistype.allocate(x, y, height, tx, ty, CANNONBALL_LAND_HEIGHT)
set .cast = c
set .lvl = lvl
set .s = s
set .fxpath = CANNONBALL_SFX
set .scale = scale
call .launch(speed, arc)
return this
endmethod
endstruct
private function SpellActions takes nothing returns nothing
local integer lvl = GetUnitAbilityLevel(SpellEvent.CastingUnit, SPELL_ID)
local real faceAng = GetUnitFacing(SpellEvent.CastingUnit) * bj_DEGTORAD
local real cx = GetUnitX(SpellEvent.CastingUnit)
local real cy = GetUnitY(SpellEvent.CastingUnit)
local real cos = Cos(faceAng)
local real sin = Sin(faceAng)
local real x
local real y
local real dist
local real ang
local integer i = -1
// Loops are done in a certain pattern as to create missiles for the front and back
// Big cannons
set dist = BigCannonDistance(lvl)
// Front & Back
loop
exitwhen i == 3
set x = cx + i * cos * BIG_CANNON_VERT_OFFSET - i * sin * BIG_CANNON_HORI_OFFSET
set y = cy + i * sin * BIG_CANNON_VERT_OFFSET + i * cos * BIG_CANNON_HORI_OFFSET
call missile.create(SpellEvent.CastingUnit, lvl, x, y, x + i * dist * cos, y + i * dist * sin, 0)
set i = i + 2
endloop
set i = -1
// Medium cannons
set dist = MediumCannonDistance(lvl)
// Front Left and Back Right
set ang = faceAng + MED_ANG_OFFSET
loop
exitwhen i == 3
set x = cx + i*cos * MED_CANNON_VERT_OFFSET - i * sin * MED_CANNON_HORI_OFFSET
set y = cy + i*sin * MED_CANNON_VERT_OFFSET + i * cos * MED_CANNON_HORI_OFFSET
call missile.create(SpellEvent.CastingUnit, lvl, x, y, x + i*dist * Cos(ang), y + i*dist * Sin(ang), 1)
set i = i + 2
endloop
set i = -1
// Front Right and Back Left
set ang = faceAng - MED_ANG_OFFSET
loop
exitwhen i == 3
set x = cx + i*cos * MED_CANNON_VERT_OFFSET + i * sin * (MED_CANNON_HORI_OFFSET + MED_CANNON_FIX_OFFSET)
set y = cy + i*sin * MED_CANNON_VERT_OFFSET - i * cos * MED_CANNON_HORI_OFFSET
call missile.create(SpellEvent.CastingUnit, lvl, x, y, x + i*dist * Cos(ang), y + i*dist * Sin(ang), 1)
set i = i + 2
endloop
set i = -1
// Small cannons
set dist = SmallCannonDistance(lvl)
// Front Left and Back Right
loop
exitwhen i == 3
set x = cx + i * cos * SMA_CANNON_VERT_OFFSET - i * sin * SMA_CANNON_HORI_OFFSET
set y = cy + i * sin * SMA_CANNON_VERT_OFFSET + i * cos * SMA_CANNON_HORI_OFFSET
call missile.create(SpellEvent.CastingUnit, lvl, x, y, x + i * dist * cos, y + i * dist * sin, 2)
set i = i + 2
endloop
set i = -1
// Front Right & Back Left
loop
exitwhen i == 3
set x = cx + i * cos * SMA_CANNON_VERT_OFFSET + i * sin * (SMA_CANNON_HORI_OFFSET + SMA_CANNON_FIX_OFFSET)
set y = cy + i * sin * SMA_CANNON_VERT_OFFSET - i * cos * SMA_CANNON_HORI_OFFSET
call missile.create(SpellEvent.CastingUnit, lvl, x, y, x + i * dist * cos, y + i * dist * sin, 2)
set i = i + 2
endloop
endfunction
private function Init takes nothing returns nothing
call RegisterSpellEffectResponse(SPELL_ID, SpellActions)
endfunction
endscope