- Joined
- Apr 8, 2011
- Messages
- 88
JASS:
library Movement requires MISC, MissilesDatabase, VectorLib, MainEngine
//globals
private Missile MStack[MAX]
private int Current = 0
private int TempId
private timer UpdateTimer = CT
private group TemporaryGroup = CG
define {
private PERIOD = 0.025
private MAX = 250
private DUMMY = 'h000'
}
struct Missile
Vector v
group in_range = CG
unit owner, from
int id, skill_id
real radius, step = 0., limit, dist
void Remove(bool flag){
if StringLength(MissileHitSound[this.id]) > 0
{ AddSound(MissileHitSound[this.id], Gx(this.owner), Gy(this.owner)) }
if flag { KillUnit(this.owner) }
else { RemoveUnit(this.owner) }
GC(this.in_range)
DG(this.in_range)
this.in_range = null
this.owner = null
this.from = null
this.v.destroy()
this.destroy()
}
endstruct
// func
private bool AOEFilter(){
return (GetHp(GetFilterUnit()) > 0.045 and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(ForFilter1)) and GetUnitAbilityLevel(GetFilterUnit(), 'Avul') == 0)
}
private void WeaponDamageGroup(){
Missile m = MStack[TempId]
UD ud = GetData(m.from)
int status
if ud.current_weapon.magic_damage {
status = MagicalDamage(m.from, GetEnumUnit(), Power[UsedEffect[m.skill_id]], true, false, UsedEffect[m.skill_id])
BroadcastDamage(status, Last_Damage, GetEnumUnit())
}
else {
status = PhysicalDamage(m.from, GetEnumUnit(), Power[UsedEffect[m.skill_id]], true, true, false, true, UsedEffect[m.skill_id])
BroadcastDamage(status, Last_Damage, GetEnumUnit())
}
}
private void MissileDamageGroup(){
Missile m = MStack[TempId]
int status
if DamageType[UsedEffect[m.skill_id]] {
status = PhysicalDamage(m.from, GetEnumUnit(), Power[UsedEffect[m.skill_id]], true, true, false, true, UsedEffect[m.skill_id])
BroadcastDamage(status, Last_Damage, GetEnumUnit())
}
else {
status = MagicalDamage(m.from, GetEnumUnit(), Power[UsedEffect[m.skill_id]], true, false, UsedEffect[m.skill_id])
BroadcastDamage(status, Last_Damage, GetEnumUnit())
}
}
//Пиначет: безалкогольное пиво - как секс с сестрой. ощущения похожи, но это неправильно!
private void MovementUpdate(){
int c = 0
real x, y, z = 0.
while(c++ < Current){
ForFilter1 = MStack[c].from
GroupEnumUnitsInRange(MStack[c].in_range, Gx(MStack[c].owner), Gy(MStack[c].owner), MStack[c].radius, Filter(function AOEFilter))
if CountGroup(MStack[c].in_range) > 0 {
if MStack[Current].skill_id == 0 {
TempId = c
ForGroup(MStack[c].in_range, function WeaponDamageGroup)
}
elseif Power[UsedEffect[MStack[Current].skill_id]][GetUnitAbilityLevel(MStack[c].from, SkillId[MStack[Current].skill_id])] > 0 {
if AreaOfEffect[UsedEffect[MStack[Current].skill_id]][GetUnitAbilityLevel(MStack[c].from, SkillId[MStack[Current].skill_id])] > 0. {
ApplyEffect(MStack[c].from, null, Gx(MStack[c].owner), Gy(MStack[c].owner), UsedEffect[MStack[Current].skill_id], GetUnitAbilityLevel(MStack[c].from, SkillId[MStack[Current].skill_id]))
}
else {
ApplyEffect(MStack[c].from, FirstOfGroup(MStack[c].in_range), 0., 0., UsedEffect[MStack[Current].skill_id], GetUnitAbilityLevel(MStack[c].from, SkillId[MStack[Current].skill_id]))
}
}
MStack[c].Remove(true)
MStack[c] = MStack[Current]
Current--
}
else {
x = Gx(MStack[c].owner)
y = Gy(MStack[c].owner)
if (GetHp(MStack[c].owner) < 0.045 or \
(x > GetRectMaxX(bj_mapInitialPlayableArea) or \
x < GetRectMinX(bj_mapInitialPlayableArea) or \
y > GetRectMaxY(bj_mapInitialPlayableArea) or \
y < GetRectMinY(bj_mapInitialPlayableArea)) or GetUnitFlyHeight(MStack[c].owner) <= 0.1) {
MStack[c].Remove(true)
MStack[c] = MStack[Current]
Current--
}
else {
z = GetUnitFlyHeight(MStack[c].owner)
if (Abs(GetZ(x + MStack[c].v.vx * PERIOD, y + MStack[c].v.vy * PERIOD) - GetZ(x, y)) > 0) {
z = z - GetZ(x + MStack[c].v.vx * PERIOD, y + MStack[c].v.vy * PERIOD) + GetZ(x, y)
}
SetUnitX(MStack[c].owner, x + MStack[c].v.vx * PERIOD)
SetUnitY(MStack[c].owner, y + MStack[c].v.vy * PERIOD)
SetUnitFlyHeight(MStack[c].owner, (z + MStack[c].v.vz * PERIOD), 0.)
//msg(R2S(z))
}
}
}
}
void PushMissile(unit from, int skill_id, real start_x, real start_y, real end_z){
int id = UsedMissile[GetSkillCell(skill_id)]
real angle = ABUC(from, start_x, start_y)
real end_x = start_x + Rx(MaxDistance[id], angle), end_y = start_y + Ry(MaxDistance[id], angle)
real z = GetZ(start_x, start_y) + GetUnitFlyHeight(from) + MissileStartZ[id]
real distance = SquareRoot((end_x-start_x)*(end_x-start_x) + (end_y-start_y)*(end_y-start_y) + (end_z - z)*(end_z - z))
//msg(R2S(end_z))
if skill_id < 0 { return }
if distance > MaxDistance[id] { distance = MaxDistance[id] }
end_z = end_z + MissileStartZ[id]
Current++
MStack[Current] = Missile.create()
MStack[Current].from = from
MStack[Current].owner = CreateUnit(GetOwningPlayer(from), DUMMY, start_x, start_y, angle)
SetUnitX(MStack[Current].owner,start_x)
SetUnitY(MStack[Current].owner,start_y)
SetUnitFlyHeight(MStack[Current].owner, z, 0.)
AddSpecialEffectTarget(MissileModel[id], MStack[Current].owner, "origin")
SetUnitScale(MStack[Current].owner, MissileScale[id], MissileScale[id], MissileScale[id])
if StringLength(MissileLaunchSound[id]) > 0
{ AddSound(MissileLaunchSound[id], Gx(MStack[Current].owner), Gy(MStack[Current].owner)) }
MStack[Current].radius = MissieRadius[id]
//MStack[Current].limit = MissileArc[MStack[Current].id]
MStack[Current].dist = distance / 10.
MStack[Current].id = id
MStack[Current].skill_id = GetSkillCell(skill_id)
MStack[Current].v.GetFrom2Loc(start_x, start_y, z, end_x, end_y, end_z)
MStack[Current].v.vx = (end_x - start_x) / distance * MissileSpeed[id]
MStack[Current].v.vy = (end_y - start_y) / distance * MissileSpeed[id]
MStack[Current].v.vz = (end_z - z) / distance * MissileSpeed[id]
if Current == 1 {
TimerStart(UpdateTimer, PERIOD, true, function MovementUpdate)
}
}
void FireWeaponShell(unit source, real x, real y){
UD ud = GetData(source)
real start_x = Gx(source), start_y = Gy(source), z = GetZ(x, y) + 60.
real start_z = GetZ(start_x, start_y) + GetUnitFlyHeight(source) + 60.
real distance, distance_to_point = DBC(source, x, y), angle = ABUC(source, x, y)
x = x + Rx(ud.current_weapon.range, angle); y = y + Ry(ud.current_weapon.range, angle)
distance = SquareRoot((x-start_x)*(x-start_x) + (y-start_y)*(y-start_y) + (z - start_z)*(z - start_z))
//if distance > ud.current_weapon.range { distance = ud.current_weapon.range }
Current++
MStack[Current] = Missile.create()
MStack[Current].from = source
MStack[Current].owner = CreateUnit(GetOwningPlayer(source), DUMMY, start_x, start_y, angle)
SetUnitX(MStack[Current].owner,start_x)
SetUnitY(MStack[Current].owner,start_y)
MStack[Current].radius = ud.current_weapon.shell_size
SetUnitFlyHeight(MStack[Current].owner, start_z, 0.)
AddSpecialEffectTarget(ud.current_weapon.model, MStack[Current].owner, "origin")
//MStack[Current].limit = ud.current_weapon.shell_limit_z
MStack[Current].dist = distance_to_point / 10.
MStack[Current].id = 0
MStack[Current].skill_id = 0
MStack[Current].v.GetFrom2Loc(start_x, start_y, start_z, x, y, z)
MStack[Current].v.vx = (x - start_x) / distance * ud.current_weapon.shell_speed
MStack[Current].v.vy = (y - start_y) / distance * ud.current_weapon.shell_speed
MStack[Current].v.vz = (z - start_z) / distance * ud.current_weapon.shell_speed
if Current == 1 {
TimerStart(UpdateTimer, PERIOD, true, function MovementUpdate)
}
}
endlibrary