Moderator
M
Moderator
Meteorites fall v1.6 | Reviewed by Maker | 6th Oct 2013 | ||||
APPROVED | ||||
|
|
//*************************************************************************************
//*************************************************************************************
//*************************************************************************************
//*************************************************************************************
// M E T E O R F A L L
// - Spell Create By:
// + Elphis
//*************************************************************************************
library MeteoritesFall /*
*/ requires /*
// -*/ DelFX /* http://www.hiveworkshop.com/forums/spells-569/delfx-delayed-effects-1-4-2-a-116064/?prev=search%3DDel%2520Effect%26d%3Dlist%26r%3D20%26c%3D112
// -*/ TimerUtils /* http://www.wc3c.net/showthread.php?t=101322
// -*/ IsTerrainWalkable /* I can't found this link of the library, so credits by Maker,anitarf
// -*/ SpellEffectEvent /* http://www.hiveworkshop.com/forums/jass-resources-412/snippet-spelleffectevent-187193/
// -*/ RegisterPlayerUnitEvent /* http://www.hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/
// -*/ xedamage /* http://www.wc3c.net/showthread.php?t=101150
// -*/ SimError /* http://www.wc3c.net/showthread.php?t=101260
// -*/ JumpTargetDamage /* Spell Staus Library */
//*************************************************************************************
// - Spell Information:
// - Calling a big meteor in sky falling ground
// when it hit a ground. This meteor will explore and deals 75/150/225/300
// damage in 300 AOE and radiating mini meteor in 500 AOE
// deals 20/40/60/80 damage.
//
//*************************************************************************************
// - Installation:
// - Import/copy the required libraries and Meteor Fall code to your map
// - Import/copy the custom ability and unit to your map and change the SPELL_ID and FIRE_ID if needed
// - You may view the raw ID of the objects by pressing CTRL+D in the object editor
// - You may play with the configurables below
//*************************************************************************************
//
globals
//==================================CONFIGURABLES=============================================//
//Spell rawcode, change if needed
private constant integer SPELL_ID = 'A000'
//Ability allow unit fly
private constant integer ABI_FLY = 'Amrf'
//Mini Meteor count
private constant integer MINI_METEOR_C = 20
//Meteor Model
private constant string METEOR_MODEL = "Abilities\\Weapons\\DemonHunterMissile\\DemonHunterMissile.mdl"
//Meteor explore
private constant string METEOR_EXPLORE = "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl"
//Model attach from Meteor, Good = origin
private constant string METEOR_ATTACHMENT = "origin"
//Displayed messages when you can't caller meteor
private constant string ERROR = "Can't call Meteor here"
//Timer calling func every time
private constant real PERIODIC = 0.031250000
//Meteor duration
private constant real METEOR_DURATION = 3.
//Damage when exploring on center Big Meteor
private constant real METEOR_DAMAGE = 75.
//Damage when exploring on mini meteor
private constant real METEOR_MINI_DAMAGE = 20.
//Max height of Meteor
private constant real METEOR_HEIGHT = 1000.
//Meteor fall speed
private constant real METEOR_FALL_SPEED = 30.
//Mini meteor explore speed
private constant real METEOR_MINI_EX_SPEED = 20.
//Mini meteor create angle
private constant real METEOR_MINI_ANGLE = 36.
//Min distance mini meteor called
private constant real METEOR_MINI_MIN = 150.
//Max distance mini meteor called
private constant real METEOR_MINI_MAX = 500.
//Damage radius of Big meteor
private constant real DAMAGE_RADIUS = 400.
//Damage radius of mini meteor
private constant real DAMAGE_RADIUS_MINI = 200.
//Big meteor Size
private constant real BIG_METEOR_SIZE = 5.
//Mini meteor Size
private constant real MINI_METEOR_SIZE = 1.
//Big meteor fall out speed
private constant real METEOR_SPEED = 20.
//Allow damage to tree
private constant boolean DAMAGE_TREE = true
//
private constant attacktype ATTACKTYPE = ATTACK_TYPE_HERO
private constant damagetype DAMAGETYPE = DAMAGE_TYPE_COLD
private constant weapontype WEAPONTYPE = WEAPON_TYPE_METAL_HEAVY_BASH
//
private xedamage xe
//==================================CONFIGURABLES=============================================//
//
endglobals
//
private struct MeteoritesFall
//
unit caster = null
unit dummy = null
real ff
real h = METEOR_HEIGHT
real f
real cos
real sin
integer level
player p = null
//Check this area can casting spell
static method terrainCheck takes nothing returns nothing
local unit caster
if GetSpellAbilityId() != SPELL_ID then
set caster = null
return
endif
//
set caster = GetTriggerUnit()
//
if not IsTerrainWalkable(GetSpellTargetX(),GetSpellTargetY()) then
call PauseUnit(caster, true)
call IssueImmediateOrderById(caster, 851972)
call PauseUnit(caster, false)
call SimError(GetTriggerPlayer(), ERROR)
endif
set caster = null
endmethod
//
static method onDamage takes unit caster returns real
return METEOR_DAMAGE //Damage of Big Meteor
endmethod
//
static method onDamageMiniMeteor takes unit caster returns real
return METEOR_MINI_DAMAGE //Damage of mini Meteor
endmethod
//Loop calling every time
static method onPeriodic takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = GetTimerData(t)
local integer i = MINI_METEOR_C
local unit d
local real x
local real y
if h > 0. then
set h = h - METEOR_SPEED
//
call SetUnitFlyHeight(dummy,h,METEOR_HEIGHT/.1)
//
set x = GetWidgetX(dummy) + cos
set y = GetWidgetY(dummy) + sin
//
call SetUnitX(dummy,x)
call SetUnitY(dummy,y)
else
call ReleaseTimer(t)
//
set f = GetWidgetX(dummy)
set ff = GetWidgetY(dummy)
call RemoveUnit(dummy)
//
loop
//
exitwhen i == 0
//
//
set cos = Cos(i*METEOR_MINI_ANGLE*0.01747)
set sin = Sin(i*METEOR_MINI_ANGLE*0.01747)
//
set x = f + METEOR_MINI_MIN * cos
set y = ff + METEOR_MINI_MIN * sin
//Calling mini meteor
set d = CreateUnit(p,XE_DUMMY_UNITID,x,y,0.)
call SetUnitScale(d,MINI_METEOR_SIZE,0,0)
call CreateDelayedEffectTarget(METEOR_MODEL,d,METEOR_ATTACHMENT,0.,METEOR_DURATION)
set x = GetWidgetX(dummy) + METEOR_MINI_MAX * cos
set y = GetWidgetY(dummy) + METEOR_MINI_MAX * sin
call Jump.JumpTarget(d,x,y,METEOR_MINI_EX_SPEED,METEOR_EXPLORE,METEOR_EXPLORE,true,false,ATTACKTYPE,DAMAGETYPE,WEAPONTYPE,DAMAGE_RADIUS_MINI,DAMAGE_TREE,caster,onDamageMiniMeteor(caster)*level)
//
set i = i - 1
//
endloop
//Deals damage to enemy
call xe.damageAOE(caster,f,ff,DAMAGE_RADIUS,onDamage(caster)*level)
//Remove Leaks
call RemoveUnit(dummy)
set d = null
set caster = null
set dummy = null
call destroy()
endif
//
set t = null
//
endmethod
//Setup spell if any unit casting this ability
static method onCast takes nothing returns nothing
local thistype this = allocate()
local real x
local real y
local real o = GetSpellTargetX()
local real z = GetSpellTargetY()
local real m = 0.
//Other config
set caster = GetTriggerUnit()
//Level of Ability
set level = GetUnitAbilityLevel(caster,SPELL_ID)
//
set p = GetTriggerPlayer()
set x = GetWidgetX(caster)
set y = GetWidgetY(caster)
set f = Angle(x,y,o,z)
set m = Distance(x,y,o,z)
//*****************************************************
//Creating Big Meteor
set dummy = CreateUnit(p,XE_DUMMY_UNITID,x,y,f)
call SetUnitScale(dummy,BIG_METEOR_SIZE,0.,0.) //Set meteor size
call CreateDelayedEffectTarget(METEOR_MODEL,dummy,METEOR_ATTACHMENT,0.,METEOR_DURATION)
if UnitAddAbility(dummy,ABI_FLY) then
call ShowUnit(dummy,false)
call UnitRemoveAbility(dummy,ABI_FLY)
call SetUnitFlyHeight(dummy,METEOR_HEIGHT,0.)
call ShowUnit(dummy,true)
endif
//
set ff = m/METEOR_HEIGHT*METEOR_SPEED
//
set cos = ff * Cos(f*0.01747)
set sin = ff * Sin(f*0.01747)
//**********************************************
//
call TimerStart(NewTimerEx(this),PERIODIC,true,function thistype.onPeriodic)
endmethod
//
static method onInit takes nothing returns nothing
//This event use for check terrain cast :)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_CAST,function thistype.terrainCheck)
//==========================================================================================
call RegisterSpellEffectEvent(SPELL_ID,function thistype.onCast)
//
//Damage config
set xe = xedamage.create()
set xe.dtype = DAMAGETYPE
set xe.atype = ATTACKTYPE
set xe.wtype = WEAPONTYPE
set xe.damageEnemies = true
set xe.damageTrees = DAMAGE_TREE
endmethod
//
endstruct
endlibrary
[/HIDDEN]
//! zinc
//
library DummRemove requires TimerUtils
{
public struct Dum
{
unit u;
//
static method Loop()
{
thistype this = GetTimerData(GetExpiredTimer());
RemoveUnit(u);
u = null;
ReleaseTimer(GetExpiredTimer());
destroy();
}
//
static method Remove(unit whatunit,real dura) -> unit
{
thistype this = allocate();
u = whatunit;
TimerStart(NewTimerEx(this),dura,false,function thistype.Loop);
return whatunit;
}
}
}
//
library JumpTargetDamage requires TimerUtils,AaD
{
constant real time = .0325;
//
public struct Jump
{
real Reach;
real Fly;
real Dis;
real Angle;
real sp;
boolean kill;
unit U;
unit C;
real High;
real d;
real Highsettings;
real Timer;
real ag;
boolean Jumpag;
boolean rem;
string EfEnd;
real radi;
real damage;
xedamage xe;
//
static method onPeriodic()
{
real x;
real y;
thistype this = GetTimerData(GetExpiredTimer());
if(!IsUnitType(U,UNIT_TYPE_DEAD) && GetUnitTypeId(U) != 0)
{
if (Reach < Dis)
{
x = GetWidgetX(U) + sp * Cos(Angle * 0.01747);
y = GetWidgetY(U) + sp * Sin(Angle * 0.01747);
SetUnitX(U,x);
SetUnitY(U,y);
Reach = Reach + sp;
Timer = Timer + 180/(Dis / sp);
Fly = Sin(Timer*0.01747)*Highsettings*1.3;
SetUnitFlyHeight(U,Fly,0.);
}
else
{
if(kill && !rem)
KillUnit(U);
if(!kill && rem)
RemoveUnit(U);
xe.damageAOE(C,GetWidgetX(U),GetWidgetY(U),radi,damage);
xe.destroy();
DestroyEffect(AddSpecialEffect(EfEnd,GetWidgetX(U),GetWidgetY(U)));
SetUnitPathing(U,true);
UnitAddAbility(U,'Amrf');
UnitRemoveAbility(U,'Amrf');
SetUnitFlyHeight(U,0.,GetUnitDefaultFlyHeight(U));
if(rem)
RemoveUnit(U);
EfEnd = null;
ReleaseTimer(GetExpiredTimer());
U = null;
destroy();
}
}
else
{
if(kill && !rem)
KillUnit(U);
if(!kill && rem)
RemoveUnit(U);
SetUnitPathing(U,true);
if (UnitAddAbility(U,'Amrf'))
UnitRemoveAbility(U,'Amrf');
SetUnitFlyHeight(U,0.,GetUnitDefaultFlyHeight(U));
if(rem)
RemoveUnit(U);
EfEnd = null;
xe.destroy();
ReleaseTimer(GetExpiredTimer());
U = null;
destroy();
}
}
static method JumpTarget(unit whatunit,real xj,real yj,real speed,string XJ,string EJ,boolean rems,boolean kills,attacktype att,damagetype damt,weapontype wea,real radius,boolean damat,unit caster,real dam)
{
thistype this;
if(!IsUnitType(whatunit,UNIT_TYPE_DEAD) && GetUnitTypeId(whatunit) != 0)
{
this = allocate();
U = whatunit;
Reach = 0.;
xe = xedamage.create();
xe.dtype = damt;
xe.atype = att;
xe.wtype = wea;
xe.damageEnemies = true;
xe.damageTrees = damat;
damage = dam;
radi = radius;
Timer = 0.;
C = caster;
rem = rems;
kill = kills;
rem = rems;
sp = speed;
Fly = 0.;
EfEnd = EJ;
Dis = Distance(GetWidgetX(whatunit),GetWidgetY(whatunit),xj,yj);
Angle = Angle(GetWidgetX(whatunit),GetWidgetY(whatunit),xj,yj);
High = .35;
Highsettings = Dis*High;
DestroyEffect(AddSpecialEffect(XJ,GetWidgetX(U),GetWidgetY(U)));
SetUnitPathing(U,false);
UnitAddAbility(U,'Amrf');
UnitRemoveAbility(U,'Amrf');
TimerStart(NewTimerEx(this),time,true,function thistype.onPeriodic);
}
}
}
}
//
library AaD
{
public function Distance(real xa,real ya,real xb,real yb) -> real
{
real dx = xb - xa;
real dy = yb - ya;
return SquareRoot(dx * dx + dy * dy);
}
//
public function Angle(real xa,real ya,real xb,real yb) -> real
{
return bj_RADTODEG * Atan2(yb - ya, xb - xa);
}
}
//! endzinc
[/HIDDEN]