Moderator
M
Moderator
16 July 2012
Bribe: A good spell. Not perfect, could use fine-tuning here and there. Approved 3.7/5.
Bribe: A good spell. Not perfect, could use fine-tuning here and there. Approved 3.7/5.
/*
==========Bouncing Bombs 1.4
==========Made by: Mckill2009
REQUIRES:
- Jass New Gen Pack (JNGP) by Vexorian
- BoundSentinel by Vexorian
- TimerUtils by Vexorian
- Vector by Anitarf
- DestructableLib by PitzerMike
HOW TO INSTALL:
- Copy ALL the triggers in the folder at the left of this screen that says "All these MUST be copied to your map".
- If you already have the "Required Libraries" in your map, then no need to copy the said library.
- Change the raw codes if needed.
FEATURES:
- You can configure how many bombs you want to create
- Much of the features are configurables, please see below
CREDITS:
- Bribe for the tip
*/
library BouncingBombs uses Vector, TimerUtils, DestructableLib, BoundSentinel
globals
//These are the raw codes, change it if necessary
private constant integer SPELL_ID = 'A000' //flame strike
private constant integer BOMB_ID = 'h000'
//Never touch these!
private vector xV
private vector yV
private vector zV
private rect REC
endglobals
globals
//Configurables
private constant integer MAX_BOMBS = 5 //maximum bombs created
private constant real AOE = 200 //aoe of the bomb when explodes
private constant real MAX_DIST = 300 //used for bombs to be at random point in SpellTargetXY
private constant real PERIODIC = 0.03125
private constant real SPEED = 15 //recommended
private constant attacktype ATK = ATTACK_TYPE_CHAOS
private constant damagetype DMG = DAMAGE_TYPE_NORMAL
private constant string SFX = "Objects\\Spawnmodels\\Human\\FragmentationShards\\FragBoomSpawn.mdl"
private constant boolean DAMAGE_ONLY_TREE = true
endglobals
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD)
endfunction
private function GetDamage takes integer i returns real
return 25 + i * 25.
endfunction
private function ParabolaZ takes real h, real d, real x returns real
return (4 * h / d) * (d - x) * (x / d)
endfunction
struct VectorLib
vector position
vector velocity
method bounce takes unit u, real x, real y returns nothing
local vector v
set .position.x = x
set .position.y = y
call .velocity.add(yV)
call .position.add(.velocity)
call .velocity.add(yV)
call zV.getTerrainPoint(.position.x, .position.y)
call SetUnitPosition(u, .position.x, .position.y)
call SetUnitFlyHeight(u, .position.z, 0.0)
if zV.z >= .position.z then
call zV.getTerrainNormal(zV.x, zV.y,4.0)
set v = vector.projectionVector(.velocity, zV)
call v.scale(-2.0)
call .velocity.add(v)
call v.destroy()
endif
endmethod
method vcreate takes unit u, real velocityX, real velocityY, real bounceheight returns nothing
set .position = vector.create(GetUnitX(u),GetUnitY(u),bounceheight)
set .velocity = vector.create(velocityX,velocityY,10)
endmethod
endstruct
private struct BB extends VectorLib
unit caster
unit missile
real duration
real damage
real angle
real distance
real distx
real height
static constant real FIXED_CREATION_HEIGHT = 100
static method getDestructables takes nothing returns boolean
local destructable d = GetFilterDestructable()
if DAMAGE_ONLY_TREE and IsDestructableTree(d) then
call KillDestructable(d)
elseif not DAMAGE_ONLY_TREE then
if GetDestructableLife(d) >= 0.405 then
call KillDestructable(d)
endif
endif
set d = null
return false
endmethod
method dest takes real x, real y returns nothing
call MoveRectTo(REC, x, y)
call EnumDestructablesInRect(REC,null,function thistype.getDestructables)
endmethod
private static method bombmovements takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = GetTimerData(t)
local unit first
local unit dummy
local real x = GetUnitX(.missile)
local real y = GetUnitY(.missile)
local real x1
local real y1
if .duration > 0 then
set .duration = .duration - PERIODIC
if .distx > 0 then
set .distx = .distx - SPEED
call SetUnitPosition(.missile, x + SPEED * Cos(.angle), y + SPEED * Sin(.angle))
call SetUnitFlyHeight(.missile, ParabolaZ(.height, .distance, .distx), 0)
else
call bounce(.missile,x,y)
if GetUnitFlyHeight(.missile) <= 10 then
call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, AOE, null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if UnitAlive(first) and IsUnitEnemy(first, GetOwningPlayer(.missile)) then
call UnitDamageTarget(.missile, first, .damage, false, false, ATK, DMG, null)
call KillUnit(.missile)
call DestroyEffect(AddSpecialEffectTarget(SFX, .missile, "chest"))
call .dest(x,y)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
endif
endif
else
if UnitAlive(.missile) then
call KillUnit(.missile)
call DestroyEffect(AddSpecialEffectTarget(SFX, .missile, "chest"))
call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, AOE, null)
call .dest(x,y)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if UnitAlive(first) and IsUnitEnemy(first, GetOwningPlayer(.missile)) then
call UnitDamageTarget(.missile, first, .damage, false, false, ATK, DMG, null)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
endif
call ReleaseTimer(t)
call .destroy()
endif
set t = null
endmethod
private static method create takes unit u, unit missile, real distance, real angle, integer level returns thistype
local thistype this = thistype.allocate()
local timer t = NewTimer()
call vcreate(u,GetRandomReal(-3,3),GetRandomReal(-3,3),100)
set .caster = u
set .missile = missile
set .distance = distance
set .distx = distance
set .angle = angle
set .height = FIXED_CREATION_HEIGHT
set .damage = GetDamage(level)
set .duration = GetRandomReal(5, 10)
call SetTimerData(t, this)
call TimerStart(t, PERIODIC, true, function thistype.bombmovements)
return this
endmethod
private static method creation takes unit u returns nothing
local integer i = 0
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real x1
local real y1
local real dx
local real dy
local unit missile
loop
set x1 = GetSpellTargetX()+GetRandomReal(50, MAX_DIST)*(GetRandomReal(-1,1))
set y1 = GetSpellTargetY()+GetRandomReal(50, MAX_DIST)*(GetRandomReal(-1,1))
set dx = x1-x
set dy = y1-y
set missile = CreateUnit(GetTriggerPlayer(), BOMB_ID, x, y, 0)
call BB.create(u, missile, SquareRoot(dx*dx+dy*dy), Atan2(y1-y, x1-x), GetUnitAbilityLevel(u, SPELL_ID))
set i = i + 1
exitwhen i==MAX_BOMBS
endloop
set missile = null
endmethod
static method go takes nothing returns boolean
if GetSpellAbilityId()==SPELL_ID then
call creation(GetTriggerUnit())
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, function thistype.go)
set xV = vector.create(1,0,30)
set yV = vector.create(0,0,-0.5)
set zV = vector.create(0,0,-0.035)
set REC = Rect(-AOE,-AOE,AOE,AOE)
set t = null
endmethod
endstruct
endlibrary