This commit is contained in:
Christoph Oelckers 2016-04-22 09:15:37 +02:00
commit 20d3a72307
18 changed files with 246 additions and 150 deletions

View File

@ -661,6 +661,10 @@ public:
// Adds the item to this actor's inventory and sets its Owner.
virtual void AddInventory (AInventory *item);
// Give an item to the actor and pick it up.
// Returns true if the item pickup succeeded.
virtual bool GiveInventory (PClassInventory *type, int amount, bool givecheat = false);
// Removes the item from the inventory list.
virtual void RemoveInventory (AInventory *item);
@ -961,6 +965,7 @@ public:
void CheckSectorTransition(sector_t *oldsec);
void UpdateRenderSectorList();
void ClearRenderSectorList();
void ClearRenderLineList();
// info for drawing
// NOTE: The first member variable *must* be snext.
@ -1097,7 +1102,8 @@ public:
// a linked list of sectors where this object appears
struct msecnode_t *touching_sectorlist; // phares 3/14/98
struct msecnode_t *render_sectorlist; // same for cross-portal rendering
struct msecnode_t *render_sectorlist; // same for cross-sectorportal rendering
struct portnode_t *render_portallist; // and for cross-lineportal
TObjPtr<AInventory> Inventory; // [RH] This actor's inventory

View File

@ -2439,32 +2439,7 @@ static void FS_GiveInventory (AActor *actor, const char * type, int amount)
return;
}
AWeapon *savedPendingWeap = actor->player != NULL? actor->player->PendingWeapon : NULL;
bool hadweap = actor->player != NULL ? actor->player->ReadyWeapon != NULL : true;
AInventory *item = static_cast<AInventory *>(Spawn (info));
// This shouldn't count for the item statistics!
item->ClearCounters();
if (info->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup)) ||
info->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus)))
{
static_cast<ABasicArmorPickup*>(item)->SaveAmount *= amount;
}
else
{
item->Amount = amount;
}
if (!item->CallTryPickup (actor))
{
item->Destroy ();
}
// If the item was a weapon, don't bring it up automatically
// unless the player was not already using a weapon.
if (savedPendingWeap != NULL && hadweap)
{
actor->player->PendingWeapon = savedPendingWeap;
}
actor->GiveInventory(info, amount);
}
//============================================================================

View File

@ -514,7 +514,7 @@ bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *mor
AActor *realme = actor->player->mo->tracer;
int realstyle = actor->player->MorphStyle;
int realhealth = actor->health;
if (P_UndoPlayerMorph(actor->player, actor->player, !!(actor->player->MorphStyle & MORPH_UNDOBYDEATHFORCED)))
if (P_UndoPlayerMorph(actor->player, actor->player, 0, !!(actor->player->MorphStyle & MORPH_UNDOBYDEATHFORCED)))
{
*morphed = realme;
*morphedstyle = realstyle;

View File

@ -575,47 +575,6 @@ const char *cht_Morph (player_t *player, PClassPlayerPawn *morphclass, bool quic
return "";
}
void GiveSpawner (player_t *player, PClassInventory *type, int amount)
{
if (player->mo == NULL || player->health <= 0)
{
return;
}
AInventory *item = static_cast<AInventory *>
(Spawn (type, player->mo->Pos(), NO_REPLACE));
if (item != NULL)
{
if (amount > 0)
{
if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup)))
{
if (static_cast<ABasicArmorPickup*>(item)->SaveAmount != 0)
{
static_cast<ABasicArmorPickup*>(item)->SaveAmount *= amount;
}
else
{
static_cast<ABasicArmorPickup*>(item)->SaveAmount *= amount;
}
}
else if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus)))
{
static_cast<ABasicArmorBonus*>(item)->SaveAmount *= amount;
}
else
{
item->Amount = MIN (amount, item->MaxAmount);
}
}
item->ClearCounters();
if (!item->CallTryPickup (player->mo))
{
item->Destroy ();
}
}
}
void cht_Give (player_t *player, const char *name, int amount)
{
enum { ALL_NO, ALL_YES, ALL_YESYES } giveall;
@ -644,26 +603,12 @@ void cht_Give (player_t *player, const char *name, int amount)
{
if (amount > 0)
{
if (player->mo)
{
player->mo->health += amount;
player->health = player->mo->health;
}
else
{
player->health += amount;
}
player->mo->health += amount;
player->health = player->mo->health;
}
else
{
if (player->mo != NULL)
{
player->health = player->mo->health = player->mo->GetMaxHealth();
}
else
{
player->health = deh.GodHealth;
}
player->health = player->mo->health = player->mo->GetMaxHealth();
}
}
@ -673,7 +618,7 @@ void cht_Give (player_t *player, const char *name, int amount)
type = PClass::FindActor(gameinfo.backpacktype);
if (type != NULL)
{
GiveSpawner (player, static_cast<PClassInventory *>(type), 1);
player->mo->GiveInventory(static_cast<PClassInventory *>(type), 1, true);
}
if (!giveall)
@ -778,7 +723,7 @@ void cht_Give (player_t *player, const char *name, int amount)
AWeapon *def = (AWeapon*)GetDefaultByType (type);
if (giveall == ALL_YESYES || !(def->WeaponFlags & WIF_CHEATNOTWEAPON))
{
GiveSpawner (player, static_cast<PClassInventory *>(type), 1);
player->mo->GiveInventory(static_cast<PClassInventory *>(type), 1, true);
}
}
}
@ -805,7 +750,7 @@ void cht_Give (player_t *player, const char *name, int amount)
// Do not give replaced items unless using "give everything"
if (giveall == ALL_YESYES || type->GetReplacement() == type)
{
GiveSpawner (player, static_cast<PClassInventory *>(type), amount <= 0 ? def->MaxAmount : amount);
player->mo->GiveInventory(static_cast<PClassInventory *>(type), amount <= 0 ? def->MaxAmount : amount, true);
}
}
}
@ -827,7 +772,7 @@ void cht_Give (player_t *player, const char *name, int amount)
// Do not give replaced items unless using "give everything"
if (giveall == ALL_YESYES || type->GetReplacement() == type)
{
GiveSpawner (player, static_cast<PClassInventory *>(type), amount <= 0 ? def->MaxAmount : amount);
player->mo->GiveInventory(static_cast<PClassInventory *>(type), amount <= 0 ? def->MaxAmount : amount, true);
}
}
}
@ -847,7 +792,7 @@ void cht_Give (player_t *player, const char *name, int amount)
}
else
{
GiveSpawner (player, static_cast<PClassInventory *>(type), amount);
player->mo->GiveInventory(static_cast<PClassInventory *>(type), amount, true);
}
return;
}

View File

@ -723,7 +723,7 @@ lightlist_t * P_GetPlaneLight(sector_t * sector, secplane_t * plane, bool unders
TArray<lightlist_t> &lightlist = sector->e->XFloor.lightlist;
double planeheight=plane->ZatPoint(sector->centerspot);
if(underside) planeheight--;
if(underside) planeheight-= EQUAL_EPSILON;
for(i = 1; i < lightlist.Size(); i++)
if (lightlist[i].plane.ZatPoint(sector->centerspot) <= planeheight)

View File

@ -1142,48 +1142,6 @@ static void ClearInventory (AActor *activator)
}
}
//============================================================================
//
// DoGiveInv
//
// Gives an item to a single actor.
//
//============================================================================
static void DoGiveInv (AActor *actor, PClassActor *info, int amount)
{
AWeapon *savedPendingWeap = actor->player != NULL
? actor->player->PendingWeapon : NULL;
bool hadweap = actor->player != NULL ? actor->player->ReadyWeapon != NULL : true;
AInventory *item = static_cast<AInventory *>(Spawn (info));
// This shouldn't count for the item statistics!
item->ClearCounters();
if (info->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup)))
{
static_cast<ABasicArmorPickup*>(item)->SaveAmount *= amount;
}
else if (info->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus)))
{
static_cast<ABasicArmorBonus*>(item)->SaveAmount *= amount;
}
else
{
item->Amount = amount;
}
if (!item->CallTryPickup (actor))
{
item->Destroy ();
}
// If the item was a weapon, don't bring it up automatically
// unless the player was not already using a weapon.
if (savedPendingWeap != NULL && hadweap && actor->player != NULL)
{
actor->player->PendingWeapon = savedPendingWeap;
}
}
//============================================================================
//
// GiveInventory
@ -1218,12 +1176,12 @@ static void GiveInventory (AActor *activator, const char *type, int amount)
for (int i = 0; i < MAXPLAYERS; ++i)
{
if (playeringame[i])
DoGiveInv (players[i].mo, info, amount);
players[i].mo->GiveInventory(static_cast<PClassInventory *>(info), amount);
}
}
else
{
DoGiveInv (activator, info, amount);
activator->GiveInventory(static_cast<PClassInventory *>(info), amount);
}
}
@ -9346,7 +9304,26 @@ scriptwait:
AActor *actor = SingleActorFromTID(STACK(1), activator);
if (actor != NULL)
{
STACK(1) = actor->Sector->lightlevel;
sector_t *sector = actor->Sector;
if (sector->e->XFloor.lightlist.Size())
{
unsigned i;
TArray<lightlist_t> &lightlist = sector->e->XFloor.lightlist;
STACK(1) = *lightlist.Last().p_lightlevel;
for (i = 1; i < lightlist.Size(); i++)
{
if (lightlist[i].plane.ZatPoint(actor) <= actor->Z())
{
STACK(1) = *lightlist[i - 1].p_lightlevel;
break;
}
}
}
else
{
STACK(1) = actor->Sector->lightlevel;
}
}
else STACK(1) = 0;
break;
@ -9436,7 +9413,7 @@ scriptwait:
{
if (activator->player)
{
if (P_UndoPlayerMorph(activator->player, activator->player, force))
if (P_UndoPlayerMorph(activator->player, activator->player, 0, force))
{
changes++;
}
@ -9462,7 +9439,7 @@ scriptwait:
{
if (actor->player)
{
if (P_UndoPlayerMorph(activator->player, actor->player, force))
if (P_UndoPlayerMorph(activator->player, actor->player, 0, force))
{
changes++;
}

View File

@ -253,7 +253,7 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t
// if ceiling already moving, don't start a second function on it
if (sec->PlaneMoving(sector_t::ceiling))
{
return NULL;
return false;
}
// new door thinker

View File

@ -102,8 +102,6 @@ struct TeaserSpeech
static FRandom pr_randomspeech("RandomSpeech");
void GiveSpawner (player_t *player, PClassActor *type);
TArray<FStrifeDialogueNode *> StrifeDialogues;
typedef TMap<int, int> FDialogueIDMap; // maps dialogue IDs to dialogue array index (for ACS)

View File

@ -44,6 +44,7 @@
#include "p_trace.h"
#include "p_checkposition.h"
#include "r_utility.h"
#include "p_blockmap.h"
#include "s_sound.h"
#include "decallib.h"
@ -5178,8 +5179,8 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
}
points *= thing->GetClass()->RDFactor;
// points and bombdamage should be the same sign
if (((int(points) * bombdamage) > 0) && P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
// points and bombdamage should be the same sign (the double cast of 'points' is needed to prevent overflows and incorrect values slipping through.)
if ((((double)int(points) * bombdamage) > 0) && P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
{ // OK to damage; target is in direct path
double vz;
double thrust;
@ -6238,6 +6239,91 @@ void P_CreateSecNodeList(AActor *thing)
}
//=============================================================================
//
// P_DelPortalnode
//
// Same for line portal nodes
//
//=============================================================================
portnode_t *P_DelPortalnode(portnode_t *node)
{
portnode_t* tp; // prev node on thing thread
portnode_t* tn; // next node on thing thread
portnode_t* sp; // prev node on sector thread
portnode_t* sn; // next node on sector thread
if (node)
{
// Unlink from the Thing thread. The Thing thread begins at
// sector_list and not from AActor->touching_sectorlist.
tp = node->m_tprev;
tn = node->m_tnext;
if (tp)
tp->m_tnext = tn;
if (tn)
tn->m_tprev = tp;
// Unlink from the sector thread. This thread begins at
// sector_t->touching_thinglist.
sp = node->m_sprev;
sn = node->m_snext;
if (sp)
sp->m_snext = sn;
else
node->m_portal->render_thinglist = sn;
if (sn)
sn->m_sprev = sp;
// Return this node to the freelist (use the same one as for msecnodes, since both types are the same size.)
P_PutSecnode(reinterpret_cast<msecnode_t *>(node));
return tn;
}
return NULL;
}
//=============================================================================
//
// P_AddPortalnode
//
//=============================================================================
portnode_t *P_AddPortalnode(FLinePortal *s, AActor *thing, portnode_t *nextnode)
{
portnode_t *node;
if (s == 0)
{
I_FatalError("AddSecnode of 0 for %s\n", thing->GetClass()->TypeName.GetChars());
}
node = reinterpret_cast<portnode_t*>(P_GetSecnode());
// killough 4/4/98, 4/7/98: mark new nodes unvisited.
node->visited = 0;
node->m_portal = s; // portal
node->m_thing = thing; // mobj
node->m_tprev = NULL; // prev node on Thing thread
node->m_tnext = nextnode; // next node on Thing thread
if (nextnode)
nextnode->m_tprev = node; // set back link on Thing
// Add new node at head of portal thread starting at s->touching_thinglist
node->m_sprev = NULL; // prev node on portal thread
node->m_snext = s->render_thinglist; // next node on portal thread
if (s->render_thinglist)
node->m_snext->m_sprev = node;
s->render_thinglist = node;
return node;
}
//==========================================================================
//
// Handle the lists used to render actors from other portal areas
@ -6249,6 +6335,27 @@ void AActor::UpdateRenderSectorList()
static const double SPRITE_SPACE = 64.;
if (Pos() != OldRenderPos && !(flags & MF_NOSECTOR))
{
// Only check if the map contains line portals
ClearRenderLineList();
if (PortalBlockmap.containsLines && Pos().XY() != OldRenderPos.XY())
{
int bx = GetBlockX(X());
int by = GetBlockX(Y());
FBoundingBox bb(X(), Y(), MIN(radius*1.5, 128.)); // Don't go further than 128 map units, even for large actors
// Are there any portals near the actor's position?
if (bx >= 0 && by >= 0 && bx < bmapwidth && by < bmapheight && PortalBlockmap(bx, by).neighborContainsLines)
{
// Go through the entire list. In most cases this is faster than setting up a blockmap iterator
for (auto &p : linePortals)
{
if (p.mType == PORTT_VISUAL) continue;
if (bb.inRange(p.mOrigin) && bb.BoxOnLineSide(p.mOrigin))
{
render_portallist = P_AddPortalnode(&p, this, render_portallist);
}
}
}
}
sector_t *sec = Sector;
double lasth = -FLT_MAX;
ClearRenderSectorList();
@ -6284,6 +6391,14 @@ void AActor::ClearRenderSectorList()
render_sectorlist = NULL;
}
void AActor::ClearRenderLineList()
{
portnode_t *node = render_portallist;
while (node)
node = P_DelPortalnode(node);
render_portallist = NULL;
}
//==========================================================================
//

View File

@ -612,6 +612,62 @@ void AActor::AddInventory (AInventory *item)
Inventory->InventoryID = InventoryID++;
}
//============================================================================
//
// AActor :: GiveInventory
//
//============================================================================
bool AActor::GiveInventory(PClassInventory *type, int amount, bool givecheat)
{
bool result = true;
AWeapon *savedPendingWeap = player != NULL ? player->PendingWeapon : NULL;
bool hadweap = player != NULL ? player->ReadyWeapon != NULL : true;
AInventory *item;
if (!givecheat)
{
item = static_cast<AInventory *>(Spawn (type));
}
else
{
item = static_cast<AInventory *>(Spawn (type, Pos(), NO_REPLACE));
if (item == NULL) return false;
}
// This shouldn't count for the item statistics!
item->ClearCounters();
if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup)))
{
static_cast<ABasicArmorPickup*>(item)->SaveAmount *= amount;
}
else if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus)))
{
static_cast<ABasicArmorBonus*>(item)->SaveAmount *= amount;
}
else
{
if (!givecheat)
item->Amount = amount;
else
item->Amount = MIN (amount, item->MaxAmount);
}
if (!item->CallTryPickup (this))
{
item->Destroy ();
result = false;
}
// If the item was a weapon, don't bring it up automatically
// unless the player was not already using a weapon.
// Don't bring it up automatically if this is called by the give cheat.
if (!givecheat && player != NULL && savedPendingWeap != NULL && hadweap)
{
player->PendingWeapon = savedPendingWeap;
}
return result;
}
//============================================================================
//
// AActor :: RemoveInventory

View File

@ -458,7 +458,7 @@ void P_SerializeWorld (FArchive &arc)
void P_SerializeWorldActors(FArchive &arc)
{
int i, j;
int i;
sector_t *sec;
for (i = 0, sec = sectors; i < numsectors; i++, sec++)

View File

@ -893,7 +893,7 @@ void P_SetupPortals()
{
if (ss.mType == PORTS_STACKEDSECTORTHING && ss.mSkybox == s.mSkybox->target)
{
s.mPartner = (&ss) - &sectorPortals[0];
s.mPartner = unsigned((&ss) - &sectorPortals[0]);
}
}
}

View File

@ -119,8 +119,8 @@ static void BuildBlockmap()
while (*list != -1)
{
line_t *ld = &lines[*list++];
if (ld->isLinePortal())
FLinePortal *port = ld->getPortal();
if (port && port->mType != PORTT_VISUAL)
{
PortalBlockmap.containsLines = true;
block.portallines.Push(ld);

View File

@ -7,6 +7,7 @@
struct FPortalGroupArray;
class ASkyViewpoint;
struct portnode_t;
//============================================================================
//
// This table holds the offsets for the different parts of a map
@ -189,6 +190,7 @@ struct FLinePortal
DAngle mAngleDiff;
double mSinRot;
double mCosRot;
portnode_t *render_thinglist;
void *mRenderData;
};

View File

@ -1481,6 +1481,18 @@ struct msecnode_t
bool visited; // killough 4/4/98, 4/7/98: used in search algorithms
};
// use the same memory layout as msecnode_t so both can be used from the same freelist.
struct portnode_t
{
FLinePortal *m_portal; // a portal containing this object
AActor *m_thing; // this object
struct portnode_t *m_tprev; // prev msecnode_t for this thing
struct portnode_t *m_tnext; // next msecnode_t for this thing
struct portnode_t *m_sprev; // prev msecnode_t for this portal
struct portnode_t *m_snext; // next msecnode_t for this portal
bool visited;
};
struct FPolyNode;
struct FMiniBSP;

View File

@ -693,7 +693,7 @@ void R_EnterPortal (PortalDrawseg* pds, int depth)
fixed_t starty = viewy;
fixed_t startz = viewz;
DVector3 savedpath[2] = { ViewPath[0], ViewPath[1] };
int savedvisibility = camera? camera->renderflags & RF_INVISIBLE : 0;
ActorRenderFlags savedvisibility = camera? camera->renderflags & RF_INVISIBLE : ActorRenderFlags::FromInt(0);
CurrentPortalUniq++;

View File

@ -268,7 +268,7 @@ ACTOR Actor native //: Thinker
native void A_DropWeaponPieces(class<Actor> p1, class<Actor> p2, class<Actor> p3);
action native A_PigPain ();
native state A_MonsterRefire(int chance, state label);
native void A_SetAngle(float angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
action native A_SetAngle(float angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_SetPitch(float pitch, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_SetRoll(float/*angle*/ roll, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_ScaleVelocity(float scale, int ptr = AAPTR_DEFAULT);

View File

@ -220,3 +220,13 @@ enum
433 = 0, Ceiling_CrushStop(0)
434 = 0, Ceiling_CrushRaiseAndStay(0)
435 = 0, Ceiling_LowerAndCrush(0)
436 = 0, Ceiling_LowerAndCrushDist(0)
437 = 0, Ceiling_CrushAndRaiseDist(0)
438 = 0, Ceiling_CrushRaiseAndStayA(0)
439 = 0, Ceiling_CrushAndRaiseA(0)
440 = 0, Ceiling_CrushAndRaiseSilentA(0)
441 = 0, Ceiling_CrushAndRaiseSilentDist(0)
442 = 0, Ceiling_CrushRaiseAndStaySilA(0)
443 = 0, Generic_Crusher(0)
444 = 0, Teleport(0)
445 = 0, Teleport_NoFog(0)