gzdoom/src/g_shared/a_fastprojectile.cpp
Christoph Oelckers bc63b70d88 Merge branch 'master' into scripting
Conflicts:
	src/actor.h
	src/fragglescript/t_func.cpp
	src/g_doom/a_bossbrain.cpp
	src/g_doom/a_revenant.cpp
	src/g_heretic/a_hereticartifacts.cpp
	src/g_heretic/a_hereticweaps.cpp
	src/g_heretic/a_knight.cpp
	src/g_hexen/a_bishop.cpp
	src/g_hexen/a_clericholy.cpp
	src/g_hexen/a_dragon.cpp
	src/g_hexen/a_firedemon.cpp
	src/g_hexen/a_flechette.cpp
	src/g_hexen/a_heresiarch.cpp
	src/g_hexen/a_hexenspecialdecs.cpp
	src/g_hexen/a_iceguy.cpp
	src/g_hexen/a_korax.cpp
	src/g_hexen/a_magelightning.cpp
	src/g_hexen/a_serpent.cpp
	src/g_hexen/a_spike.cpp
	src/g_hexen/a_wraith.cpp
	src/g_raven/a_minotaur.cpp
	src/g_shared/a_bridge.cpp
	src/g_shared/a_pickups.cpp
	src/g_shared/a_randomspawner.cpp
	src/g_strife/a_alienspectres.cpp
	src/g_strife/a_crusader.cpp
	src/g_strife/a_entityboss.cpp
	src/g_strife/a_inquisitor.cpp
	src/g_strife/a_loremaster.cpp
	src/g_strife/a_programmer.cpp
	src/g_strife/a_sentinel.cpp
	src/g_strife/a_spectral.cpp
	src/g_strife/a_strifestuff.cpp
	src/g_strife/a_strifeweapons.cpp
	src/g_strife/a_thingstoblowup.cpp
	src/p_local.h
	src/r_utility.cpp
2016-01-19 13:43:11 +01:00

184 lines
3.8 KiB
C++

#include "a_sharedglobal.h"
#include "p_local.h"
#include "g_level.h"
#include "r_sky.h"
#include "p_lnspec.h"
IMPLEMENT_CLASS(AFastProjectile)
//----------------------------------------------------------------------------
//
// AFastProjectile :: Tick
//
// Thinker for the ultra-fast projectiles used by Heretic and Hexen
//
//----------------------------------------------------------------------------
void AFastProjectile::Tick ()
{
int i;
fixed_t xfrac;
fixed_t yfrac;
fixed_t zfrac;
int changexy;
PrevX = X();
PrevY = Y();
PrevZ = Z();
fixed_t oldz = Z();
PrevAngle = angle;
if (!(flags5 & MF5_NOTIMEFREEZE))
{
//Added by MC: Freeze mode.
if (bglobal.freeze || level.flags2 & LEVEL2_FROZEN)
{
return;
}
}
// [RH] Ripping is a little different than it was in Hexen
FCheckPosition tm(!!(flags2 & MF2_RIP));
int shift = 3;
int count = 8;
if (radius > 0)
{
while ( ((abs(velx) >> shift) > radius) || ((abs(vely) >> shift) > radius))
{
// we need to take smaller steps.
shift++;
count<<=1;
}
}
// Handle movement
if (velx || vely || (Z() != floorz) || velz)
{
xfrac = velx >> shift;
yfrac = vely >> shift;
zfrac = velz >> shift;
changexy = xfrac || yfrac;
int ripcount = count >> 3;
for (i = 0; i < count; i++)
{
if (changexy)
{
if (--ripcount <= 0)
{
tm.LastRipped = NULL; // [RH] Do rip damage each step, like Hexen
}
if (!P_TryMove (this, X() + xfrac,Y() + yfrac, true, NULL, tm))
{ // Blocked move
if (!(flags3 & MF3_SKYEXPLODE))
{
if (tm.ceilingline &&
tm.ceilingline->backsector &&
tm.ceilingline->backsector->GetTexture(sector_t::ceiling) == skyflatnum &&
Z() >= tm.ceilingline->backsector->ceilingplane.ZatPoint (this))
{
// Hack to prevent missiles exploding against the sky.
// Does not handle sky floors.
Destroy ();
return;
}
// [RH] Don't explode on horizon lines.
if (BlockingLine != NULL && BlockingLine->special == Line_Horizon)
{
Destroy ();
return;
}
}
P_ExplodeMissile (this, BlockingLine, BlockingMobj);
return;
}
}
AddZ(zfrac);
UpdateWaterLevel (oldz);
oldz = Z();
if (Z() <= floorz)
{ // Hit the floor
if (floorpic == skyflatnum && !(flags3 & MF3_SKYEXPLODE))
{
// [RH] Just remove the missile without exploding it
// if this is a sky floor.
Destroy ();
return;
}
SetZ(floorz);
P_HitFloor (this);
P_ExplodeMissile (this, NULL, NULL);
return;
}
if (Top() > ceilingz)
{ // Hit the ceiling
if (ceilingpic == skyflatnum && !(flags3 & MF3_SKYEXPLODE))
{
Destroy ();
return;
}
SetZ(ceilingz - height);
P_ExplodeMissile (this, NULL, NULL);
return;
}
if (changexy && ripcount <= 0)
{
ripcount = count >> 3;
Effect();
}
}
}
// Advance the state
if (tics != -1)
{
if (tics > 0) tics--;
while (!tics)
{
if (!SetState (state->GetNextState ()))
{ // mobj was removed
return;
}
}
}
}
void AFastProjectile::Effect()
{
//if (pr_smoke() < 128) // [RH] I think it looks better if it's consistent
{
FName name = GetClass()->MissileName;
if (name != NAME_None)
{
fixed_t hitz = Z()-8*FRACUNIT;
if (hitz < floorz)
{
hitz = floorz;
}
// Do not clip this offset to the floor.
hitz += GetClass()->MissileHeight;
PClassActor *trail = PClass::FindActor(name);
if (trail != NULL)
{
AActor *act = Spawn (trail, X(), Y(), hitz, ALLOW_REPLACE);
if (act != NULL)
{
act->angle = this->angle;
}
}
}
}
}