This commit is contained in:
Christoph Oelckers 2014-05-08 09:49:00 +02:00
commit 6988156d0f
9 changed files with 250 additions and 202 deletions

View file

@ -765,8 +765,8 @@ public:
} }
// These also set CF_INTERPVIEW for players. // These also set CF_INTERPVIEW for players.
void SetPitch(int p); void SetPitch(int p, bool interpolate);
void SetAngle(angle_t ang); void SetAngle(angle_t ang, bool interpolate);
const PClass *GetBloodType(int type = 0) const const PClass *GetBloodType(int type = 0) const
{ {
@ -1011,6 +1011,8 @@ public:
bool isSlow(); bool isSlow();
void SetIdle(); void SetIdle();
void ClearCounters(); void ClearCounters();
FState *GetRaiseState();
void Revive();
FState *FindState (FName label) const FState *FindState (FName label) const
{ {

View file

@ -1052,6 +1052,12 @@ void NetUpdate (void)
if (singletics) if (singletics)
return; // singletic update is synchronous return; // singletic update is synchronous
if (demoplayback)
{
nettics[0] = (maketic / ticdup);
return; // Don't touch netcmd data while playing a demo, as it'll already exist.
}
// If maketic didn't cross a ticdup boundary, only send packets // If maketic didn't cross a ticdup boundary, only send packets
// to players waiting for resends. // to players waiting for resends.
resendOnly = (maketic / ticdup) == (maketic - i) / ticdup; resendOnly = (maketic / ticdup) == (maketic - i) / ticdup;

View file

@ -4263,6 +4263,18 @@ enum EACSFunctions
ACSF_SetLineActivation, ACSF_SetLineActivation,
ACSF_GetLineActivation, ACSF_GetLineActivation,
ACSF_GetActorPowerupTics, ACSF_GetActorPowerupTics,
ACSF_ChangeActorAngle,
ACSF_ChangeActorPitch, // 80
/* Zandronum's - these must be skipped when we reach 99!
-100:ResetMap(0),
-101 : PlayerIsSpectator(1),
-102 : ConsolePlayerNumber(0),
-103 : GetTeamProperty(2),
-104 : GetPlayerLivesLeft(1),
-105 : SetPlayerLivesLeft(2),
-106 : KickFromGame(2),
*/
// ZDaemon // ZDaemon
ACSF_GetTeamScore = 19620, // (int team) ACSF_GetTeamScore = 19620, // (int team)
@ -4522,6 +4534,50 @@ static bool DoSpawnDecal(AActor *actor, const FDecalTemplate *tpl, int flags, an
angle, distance, !!(flags & SDF_PERMANENT)); angle, distance, !!(flags & SDF_PERMANENT));
} }
static void SetActorAngle(AActor *activator, int tid, int angle, bool interpolate)
{
if (tid == 0)
{
if (activator != NULL)
{
activator->SetAngle(angle << 16, interpolate);
}
}
else
{
FActorIterator iterator(tid);
AActor *actor;
while ((actor = iterator.Next()))
{
actor->SetAngle(angle << 16, interpolate);
}
}
}
static void SetActorPitch(AActor *activator, int tid, int angle, bool interpolate)
{
if (tid == 0)
{
if (activator != NULL)
{
activator->SetPitch(angle << 16, interpolate);
}
}
else
{
FActorIterator iterator(tid);
AActor *actor;
while ((actor = iterator.Next()))
{
actor->SetPitch(angle << 16, interpolate);
}
}
}
int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const SDWORD *stack, int stackdepth) int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const SDWORD *stack, int stackdepth)
{ {
AActor *actor; AActor *actor;
@ -5349,6 +5405,20 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
} }
break; break;
case ACSF_ChangeActorAngle:
if (argCount >= 2)
{
SetActorAngle(activator, args[0], args[1], argCount > 2 ? !!args[2] : false);
}
break;
case ACSF_ChangeActorPitch:
if (argCount >= 2)
{
SetActorPitch(activator, args[0], args[1], argCount > 2 ? !!args[2] : false);
}
break;
default: default:
break; break;
} }
@ -8323,44 +8393,12 @@ scriptwait:
break; break;
case PCD_SETACTORANGLE: // [GRB] case PCD_SETACTORANGLE: // [GRB]
if (STACK(2) == 0) SetActorAngle(activator, STACK(2), STACK(1), false);
{
if (activator != NULL)
{
activator->SetAngle(STACK(1) << 16);
}
}
else
{
FActorIterator iterator (STACK(2));
AActor *actor;
while ( (actor = iterator.Next ()) )
{
actor->SetAngle(STACK(1) << 16);
}
}
sp -= 2; sp -= 2;
break; break;
case PCD_SETACTORPITCH: case PCD_SETACTORPITCH:
if (STACK(2) == 0) SetActorPitch(activator, STACK(2), STACK(1), false);
{
if (activator != NULL)
{
activator->SetPitch(STACK(1) << 16);
}
}
else
{
FActorIterator iterator (STACK(2));
AActor *actor;
while ( (actor = iterator.Next ()) )
{
actor->SetPitch(STACK(1) << 16);
}
}
sp -= 2; sp -= 2;
break; break;

View file

@ -2520,32 +2520,20 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
fixed_t viletryx = self->x + FixedMul (absSpeed, xspeed[self->movedir]); fixed_t viletryx = self->x + FixedMul (absSpeed, xspeed[self->movedir]);
fixed_t viletryy = self->y + FixedMul (absSpeed, yspeed[self->movedir]); fixed_t viletryy = self->y + FixedMul (absSpeed, yspeed[self->movedir]);
AActor *corpsehit; AActor *corpsehit;
FState *raisestate;
FBlockThingsIterator it(FBoundingBox(viletryx, viletryy, 32*FRACUNIT)); FBlockThingsIterator it(FBoundingBox(viletryx, viletryy, 32*FRACUNIT));
while ((corpsehit = it.Next())) while ((corpsehit = it.Next()))
{ {
if (!(corpsehit->flags & MF_CORPSE) ) FState *raisestate = corpsehit->GetRaiseState();
continue; // not a monster if (raisestate != NULL)
{
if (corpsehit->tics != -1 && // not lying still yet
!corpsehit->state->GetCanRaise()) // or not ready to be raised yet
continue;
raisestate = corpsehit->FindState(NAME_Raise);
if (raisestate == NULL)
continue; // monster doesn't have a raise state
if (corpsehit->IsKindOf(RUNTIME_CLASS(APlayerPawn)))
continue; // do not resurrect players
// use the current actor's radius instead of the Arch Vile's default. // use the current actor's radius instead of the Arch Vile's default.
fixed_t maxdist = corpsehit->GetDefault()->radius + self->radius; fixed_t maxdist = corpsehit->GetDefault()->radius + self->radius;
maxdist = corpsehit-> GetDefault()->radius + self->radius; maxdist = corpsehit->GetDefault()->radius + self->radius;
if ( abs(corpsehit-> x - viletryx) > maxdist || if (abs(corpsehit->x - viletryx) > maxdist ||
abs(corpsehit-> y - viletryy) > maxdist ) abs(corpsehit->y - viletryy) > maxdist)
continue; // not actually touching continue; // not actually touching
#ifdef _3DFLOORS #ifdef _3DFLOORS
// Let's check if there are floors in between the archvile and its target // Let's check if there are floors in between the archvile and its target
@ -2576,7 +2564,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
corpsehit->flags |= MF_SOLID; corpsehit->flags |= MF_SOLID;
corpsehit->height = corpsehit->GetDefault()->height; corpsehit->height = corpsehit->GetDefault()->height;
bool check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y); bool check = P_CheckPosition(corpsehit, corpsehit->x, corpsehit->y);
corpsehit->flags = oldflags; corpsehit->flags = oldflags;
corpsehit->radius = oldradius; corpsehit->radius = oldradius;
corpsehit->height = oldheight; corpsehit->height = oldheight;
@ -2585,7 +2573,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
// got one! // got one!
temp = self->target; temp = self->target;
self->target = corpsehit; self->target = corpsehit;
A_FaceTarget (self); A_FaceTarget(self);
if (self->flags & MF_FRIENDLY) if (self->flags & MF_FRIENDLY)
{ {
// If this is a friendly Arch-Vile (which is turning the resurrected monster into its friend) // If this is a friendly Arch-Vile (which is turning the resurrected monster into its friend)
@ -2600,7 +2588,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
FState * state = self->FindState(NAME_Heal); FState * state = self->FindState(NAME_Heal);
if (state != NULL) if (state != NULL)
{ {
self->SetState (state); self->SetState(state);
} }
else if (usevilestates) else if (usevilestates)
{ {
@ -2609,11 +2597,11 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
const PClass *archvile = PClass::FindClass("Archvile"); const PClass *archvile = PClass::FindClass("Archvile");
if (archvile != NULL) if (archvile != NULL)
{ {
self->SetState (archvile->ActorInfo->FindState(NAME_Heal)); self->SetState(archvile->ActorInfo->FindState(NAME_Heal));
} }
} }
S_Sound (corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE); S_Sound(corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE);
info = corpsehit->GetDefault (); info = corpsehit->GetDefault();
if (corpsehit->state == corpsehit->FindState(NAME_GenericCrush)) if (corpsehit->state == corpsehit->FindState(NAME_GenericCrush))
{ {
@ -2643,30 +2631,17 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
corpsehit->height = info->height; // [RH] Use real mobj height corpsehit->height = info->height; // [RH] Use real mobj height
corpsehit->radius = info->radius; // [RH] Use real radius corpsehit->radius = info->radius; // [RH] Use real radius
} }
corpsehit->flags = info->flags;
corpsehit->flags2 = info->flags2;
corpsehit->flags3 = info->flags3;
corpsehit->flags4 = info->flags4;
corpsehit->flags5 = info->flags5;
corpsehit->flags6 = info->flags6;
corpsehit->flags7 = info->flags7;
corpsehit->health = corpsehit->SpawnHealth();
corpsehit->target = NULL;
corpsehit->lastenemy = NULL;
// [RH] If it's a monster, it gets to count as another kill corpsehit->Revive();
if (corpsehit->CountsAsKill())
{
level.total_monsters++;
}
// You are the Archvile's minion now, so hate what it hates // You are the Archvile's minion now, so hate what it hates
corpsehit->CopyFriendliness (self, false); corpsehit->CopyFriendliness(self, false);
corpsehit->SetState (raisestate); corpsehit->SetState(raisestate);
return true; return true;
} }
} }
}
return false; return false;
} }

View file

@ -1,4 +1,5 @@
// Emacs style mode select -*- C++ -*- // Emacs style mode select -*- C++ -*-
// Emacs style mode select -*- C++ -*-
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// $Id:$ // $Id:$
@ -2973,24 +2974,24 @@ void AActor::SetShade (int r, int g, int b)
fillcolor = MAKEARGB(ColorMatcher.Pick (r, g, b), r, g, b); fillcolor = MAKEARGB(ColorMatcher.Pick (r, g, b), r, g, b);
} }
void AActor::SetPitch(int p) void AActor::SetPitch(int p, bool interpolate)
{ {
if (p != pitch) if (p != pitch)
{ {
pitch = p; pitch = p;
if (player != NULL) if (player != NULL && interpolate)
{ {
player->cheats |= CF_INTERPVIEW; player->cheats |= CF_INTERPVIEW;
} }
} }
} }
void AActor::SetAngle(angle_t ang) void AActor::SetAngle(angle_t ang, bool interpolate)
{ {
if (ang != angle) if (ang != angle)
{ {
angle = ang; angle = ang;
if (player != NULL) if (player != NULL && interpolate)
{ {
player->cheats |= CF_INTERPVIEW; player->cheats |= CF_INTERPVIEW;
} }
@ -6074,6 +6075,49 @@ int AActor::SpawnHealth()
} }
} }
FState *AActor::GetRaiseState()
{
if (!(flags & MF_CORPSE))
{
return NULL; // not a monster
}
if (tics != -1 && // not lying still yet
!state->GetCanRaise()) // or not ready to be raised yet
{
return NULL;
}
if (IsKindOf(RUNTIME_CLASS(APlayerPawn)))
{
return NULL; // do not resurrect players
}
return FindState(NAME_Raise);
}
void AActor::Revive()
{
AActor *info = GetDefault();
flags = info->flags;
flags2 = info->flags2;
flags3 = info->flags3;
flags4 = info->flags4;
flags5 = info->flags5;
flags6 = info->flags6;
flags7 = info->flags7;
DamageType = info->DamageType;
health = SpawnHealth();
target = NULL;
lastenemy = NULL;
// [RH] If it's a monster, it gets to count as another kill
if (CountsAsKill())
{
level.total_monsters++;
}
}
FDropItem *AActor::GetDropItems() FDropItem *AActor::GetDropItems()
{ {
unsigned int index = GetClass()->Meta.GetMetaInt (ACMETA_DropItems) - 1; unsigned int index = GetClass()->Meta.GetMetaInt (ACMETA_DropItems) - 1;

View file

@ -410,18 +410,11 @@ void P_RemoveThing(AActor * actor)
bool P_Thing_Raise(AActor *thing) bool P_Thing_Raise(AActor *thing)
{ {
if (thing == NULL) FState * RaiseState = thing->GetRaiseState();
return false; // not valid
if (!(thing->flags & MF_CORPSE) )
return true; // not a corpse
if (thing->tics != -1)
return true; // not lying still yet
FState * RaiseState = thing->FindState(NAME_Raise);
if (RaiseState == NULL) if (RaiseState == NULL)
{
return true; // monster doesn't have a raise state return true; // monster doesn't have a raise state
}
AActor *info = thing->GetDefault (); AActor *info = thing->GetDefault ();
@ -443,25 +436,12 @@ bool P_Thing_Raise(AActor *thing)
return false; return false;
} }
S_Sound (thing, CHAN_BODY, "vile/raise", 1, ATTN_IDLE); S_Sound (thing, CHAN_BODY, "vile/raise", 1, ATTN_IDLE);
thing->SetState (RaiseState); thing->Revive();
thing->flags = info->flags;
thing->flags2 = info->flags2;
thing->flags3 = info->flags3;
thing->flags4 = info->flags4;
thing->flags5 = info->flags5;
thing->flags6 = info->flags6;
thing->flags7 = info->flags7;
thing->health = info->health;
thing->target = NULL;
thing->lastenemy = NULL;
// [RH] If it's a monster, it gets to count as another kill thing->SetState (RaiseState);
if (thing->CountsAsKill())
{
level.total_monsters++;
}
return true; return true;
} }

View file

@ -3931,12 +3931,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MonsterRefire)
// Set actor's angle (in degrees). // Set actor's angle (in degrees).
// //
//=========================================================================== //===========================================================================
enum
{
SPF_FORCECLAMP = 1, // players always clamp
SPF_INTERPOLATE = 2,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle)
{ {
ACTION_PARAM_START(1); ACTION_PARAM_START(2);
ACTION_PARAM_ANGLE(angle, 0); ACTION_PARAM_ANGLE(angle, 0);
self->SetAngle(angle); ACTION_PARAM_INT(flags, 1)
self->SetAngle(angle, !!(flags & SPF_INTERPOLATE));
} }
//=========================================================================== //===========================================================================
@ -3947,11 +3954,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle)
// //
//=========================================================================== //===========================================================================
enum
{
SPF_FORCECLAMP = 1, // players always clamp
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch)
{ {
ACTION_PARAM_START(2); ACTION_PARAM_START(2);
@ -3974,7 +3976,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch)
} }
pitch = clamp<int>(pitch, min, max); pitch = clamp<int>(pitch, min, max);
} }
self->SetPitch(pitch); self->SetPitch(pitch, !!(flags & SPF_INTERPOLATE));
} }
//=========================================================================== //===========================================================================

View file

@ -289,7 +289,7 @@ ACTOR Actor native //: Thinker
action native A_DropWeaponPieces(class<Actor> p1, class<Actor> p2, class<Actor> p3); action native A_DropWeaponPieces(class<Actor> p1, class<Actor> p2, class<Actor> p3);
action native A_PigPain (); action native A_PigPain ();
action native A_MonsterRefire(int chance, state label); action native A_MonsterRefire(int chance, state label);
action native A_SetAngle(float angle = 0); action native A_SetAngle(float angle = 0, int flags = 0);
action native A_SetPitch(float pitch, int flags = 0); action native A_SetPitch(float pitch, int flags = 0);
action native A_ScaleVelocity(float scale); action native A_ScaleVelocity(float scale);
action native A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0); action native A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0);

View file

@ -307,8 +307,9 @@ Const Int WARPF_STOP = 0x80;
Const Int WARPF_TOFLOOR = 0x100; Const Int WARPF_TOFLOOR = 0x100;
Const Int WARPF_TESTONLY = 0x200; Const Int WARPF_TESTONLY = 0x200;
// flags for A_SetPitch // flags for A_SetPitch/SetAngle
const int SPF_FORCECLAMP = 1; const int SPF_FORCECLAMP = 1;
const int SPF_INTERPOLATE = 2;
// flags for A_CheckLOF // flags for A_CheckLOF