diff --git a/game-music-emu/gme/gme_types.h b/game-music-emu/gme/gme_types.h old mode 100644 new mode 100755 index 06226f4aa1..bd3670e64b --- a/game-music-emu/gme/gme_types.h +++ b/game-music-emu/gme/gme_types.h @@ -1,11 +1,13 @@ #ifndef GME_TYPES_H #define GME_TYPES_H -/* - * This is a default gme_types.h for use when *not* using - * CMake. If CMake is in use gme_types.h.in will be - * processed instead. +/* CMake will either define the following to 1, or #undef it, + * depending on the options passed to CMake. This is used to + * conditionally compile in the various emulator types. + * + * See gme_type_list() in gme.cpp */ + #define USE_GME_AY #define USE_GME_GBS #define USE_GME_GYM diff --git a/src/actor.h b/src/actor.h index 03891c8ba5..60e1521322 100644 --- a/src/actor.h +++ b/src/actor.h @@ -33,6 +33,7 @@ // States are tied to finite states are tied to animation frames. #include "info.h" +#include #include "doomdef.h" #include "textures/textures.h" #include "r_data/renderstyle.h" @@ -561,8 +562,14 @@ inline T *GetDefault () struct line_t; struct secplane_t; +struct msecnode_t; struct FStrifeDialogueNode; +struct FLinkContext +{ + msecnode_t *sector_list = nullptr; +}; + class DDropItem : public DObject { DECLARE_CLASS(DDropItem, DObject) @@ -1035,6 +1042,7 @@ public: struct sector_t *ceilingsector; FTextureID ceilingpic; // contacted sec ceilingpic double radius, Height; // for movement checking + double renderradius; double projectilepassheight; // height for clipping projectile movement against this actor @@ -1141,6 +1149,8 @@ public: struct msecnode_t *touching_sectorlist; // phares 3/14/98 struct msecnode_t *render_sectorlist; // same for cross-sectorportal rendering struct portnode_t *render_portallist; // and for cross-lineportal + std::forward_list* touching_render_sectors; // this is the list of sectors that this thing interesects with it's max(radius, renderradius). + int validcount; TObjPtr Inventory; // [RH] This actor's inventory @@ -1216,8 +1226,8 @@ private: bool FixMapthingPos(); public: - void LinkToWorld (bool spawningmapthing=false, sector_t *sector = NULL); - void UnlinkFromWorld (); + void LinkToWorld (FLinkContext *ctx, bool spawningmapthing=false, sector_t *sector = NULL); + void UnlinkFromWorld(FLinkContext *ctx); void AdjustFloorClip (); bool InStateSequence(FState * newstate, FState * basestate); int GetTics(FState * newstate); diff --git a/src/b_game.cpp b/src/b_game.cpp index 9d6419787e..b99b97a609 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -118,23 +118,24 @@ void FCajunMaster::Main () } //Check if player should go observer. Or un observe + FLinkContext ctx; if (bot_observer && !observer && !netgame) { Printf ("%s is now observer\n", players[consoleplayer].userinfo.GetName()); observer = true; - players[consoleplayer].mo->UnlinkFromWorld (); + players[consoleplayer].mo->UnlinkFromWorld (&ctx); players[consoleplayer].mo->flags = MF_DROPOFF|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH|MF_NOGRAVITY|MF_FRIENDLY; players[consoleplayer].mo->flags2 |= MF2_FLY; - players[consoleplayer].mo->LinkToWorld (); + players[consoleplayer].mo->LinkToWorld (&ctx); } else if (!bot_observer && observer && !netgame) //Go back { Printf ("%s returned to the fray\n", players[consoleplayer].userinfo.GetName()); observer = false; - players[consoleplayer].mo->UnlinkFromWorld (); + players[consoleplayer].mo->UnlinkFromWorld (&ctx); players[consoleplayer].mo->flags = MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY; players[consoleplayer].mo->flags2 &= ~MF2_FLY; - players[consoleplayer].mo->LinkToWorld (); + players[consoleplayer].mo->LinkToWorld (&ctx); } } diff --git a/src/c_console.cpp b/src/c_console.cpp index 0a324eb8ff..faeec0a68b 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -1573,7 +1573,7 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) static TArray command; const size_t length = buffer.Text.Len(); - command.Resize(length + 1); + command.Resize(unsigned(length + 1)); memcpy(&command[0], buffer.Text.GetChars(), length); command[length] = '\0'; diff --git a/src/compatibility.cpp b/src/compatibility.cpp index 60f9d8ad6a..742f43eeed 100644 --- a/src/compatibility.cpp +++ b/src/compatibility.cpp @@ -533,8 +533,9 @@ void SetCompatibilityParams() if (CompatParams[i+1] < numsectors) { sector_t *sec = §ors[CompatParams[i+1]]; - sec->floorplane.ChangeHeight(CompatParams[i+2]); - sec->ChangePlaneTexZ(sector_t::floor, CompatParams[i+2] / 65536.); + const double delta = CompatParams[i + 2] / 65536.0; + sec->floorplane.ChangeHeight(delta); + sec->ChangePlaneTexZ(sector_t::floor, delta); } i += 3; break; diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 7cd599b11d..4670807e72 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -2677,13 +2677,13 @@ void FParser::SF_PlayerWeapon() if (playernum==-1) return; if (weaponnum<0 || weaponnum>9) { - script_error("weaponnum out of range! %s\n", weaponnum); + script_error("weaponnum out of range! %d\n", weaponnum); return; } PClassWeapon * ti = static_cast(PClass::FindActor(WeaponNames[weaponnum])); if (!ti) { - script_error("incompatibility in playerweapon\n", weaponnum); + script_error("incompatibility in playerweapon %d\n", weaponnum); return; } @@ -2758,13 +2758,13 @@ void FParser::SF_PlayerSelectedWeapon() if (weaponnum<0 || weaponnum>=9) { - script_error("weaponnum out of range! %s\n", weaponnum); + script_error("weaponnum out of range! %d\n", weaponnum); return; } PClassWeapon * ti = static_cast(PClass::FindActor(WeaponNames[weaponnum])); if (!ti) { - script_error("incompatibility in playerweapon\n", weaponnum); + script_error("incompatibility in playerweapon %d\n", weaponnum); return; } diff --git a/src/g_doomedmap.cpp b/src/g_doomedmap.cpp index b3aa966c30..6d7ba6796f 100644 --- a/src/g_doomedmap.cpp +++ b/src/g_doomedmap.cpp @@ -246,7 +246,7 @@ void FMapInfoParser::ParseDoomEdNums() } if (error > 0) { - sc.ScriptError("%d errors encountered in DoomEdNum definition"); + sc.ScriptError("%d errors encountered in DoomEdNum definition", error); } } diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 42af5e87f7..f019a80534 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -636,14 +636,9 @@ void AInventory::BecomeItem () { if (!(flags & (MF_NOBLOCKMAP|MF_NOSECTOR))) { - UnlinkFromWorld (); - if (sector_list) - { - P_DelSeclist (sector_list); - sector_list = NULL; - } + UnlinkFromWorld (nullptr); flags |= MF_NOBLOCKMAP|MF_NOSECTOR; - LinkToWorld (); + LinkToWorld (nullptr); } RemoveFromHash (); flags &= ~MF_SPECIAL; @@ -674,9 +669,9 @@ void AInventory::BecomePickup () } if (flags & (MF_NOBLOCKMAP|MF_NOSECTOR)) { - UnlinkFromWorld (); + UnlinkFromWorld (nullptr); flags &= ~(MF_NOBLOCKMAP|MF_NOSECTOR); - LinkToWorld (); + LinkToWorld (nullptr); P_FindFloorCeiling (this); } flags = (GetDefault()->flags | MF_DROPPED) & ~MF_COUNTITEM; diff --git a/src/g_level.cpp b/src/g_level.cpp index 4bb78461af..321810589c 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1196,8 +1196,7 @@ void G_StartTravel () // Only living players travel. Dead ones get a new body on the new level. if (players[i].health > 0) { - pawn->UnlinkFromWorld (); - P_DelSector_List (); + pawn->UnlinkFromWorld (nullptr); int tid = pawn->tid; // Save TID pawn->RemoveFromHash (); pawn->tid = tid; // Restore TID (but no longer linked into the hash chain) @@ -1206,8 +1205,7 @@ void G_StartTravel () for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory) { inv->ChangeStatNum (STAT_TRAVELLING); - inv->UnlinkFromWorld (); - P_DelSector_List (); + inv->UnlinkFromWorld (nullptr); } } } @@ -1304,7 +1302,7 @@ void G_FinishTravel () { pawndup->Destroy(); } - pawn->LinkToWorld (); + pawn->LinkToWorld (nullptr); pawn->ClearInterpolation(); pawn->AddToHash (); pawn->SetState(pawn->SpawnState); @@ -1313,7 +1311,7 @@ void G_FinishTravel () for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory) { inv->ChangeStatNum (STAT_INVENTORY); - inv->LinkToWorld (); + inv->LinkToWorld (nullptr); inv->Travelled (); } if (ib_compatflags & BCOMPATF_RESETPLAYERSPEED) diff --git a/src/g_pch.h b/src/g_pch.h index a22649815a..2c3676f5ac 100644 --- a/src/g_pch.h +++ b/src/g_pch.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/src/g_shared/a_movingcamera.cpp b/src/g_shared/a_movingcamera.cpp index a1ffe5dc60..c09d93fd55 100644 --- a/src/g_shared/a_movingcamera.cpp +++ b/src/g_shared/a_movingcamera.cpp @@ -364,6 +364,7 @@ void APathFollower::NewNode () bool APathFollower::Interpolate () { DVector3 dpos(0, 0, 0); + FLinkContext ctx; if ((args[2] & 8) && Time > 0.f) { @@ -372,7 +373,7 @@ bool APathFollower::Interpolate () if (CurrNode->Next==NULL) return false; - UnlinkFromWorld (); + UnlinkFromWorld (&ctx); DVector3 newpos; if (args[2] & 1) { // linear @@ -389,7 +390,7 @@ bool APathFollower::Interpolate () newpos.Z = Splerp(PrevNode->Z(), CurrNode->Z(), CurrNode->Next->Z(), CurrNode->Next->Next->Z()); } SetXYZ(newpos); - LinkToWorld (); + LinkToWorld (&ctx); if (args[2] & 6) { @@ -541,10 +542,11 @@ void AActorMover::Activate (AActor *activator) tracer->flags |= MF_NOGRAVITY; if (args[2] & 128) { - tracer->UnlinkFromWorld (); + FLinkContext ctx; + tracer->UnlinkFromWorld (&ctx); tracer->flags |= MF_NOBLOCKMAP; tracer->flags &= ~MF_SOLID; - tracer->LinkToWorld (); + tracer->LinkToWorld (&ctx); } if (tracer->flags3 & MF3_ISMONSTER) { @@ -563,9 +565,10 @@ void AActorMover::Deactivate (AActor *activator) Super::Deactivate (activator); if (tracer != NULL) { - tracer->UnlinkFromWorld (); + FLinkContext ctx; + tracer->UnlinkFromWorld (&ctx); tracer->flags = ActorFlags::FromInt (special1); - tracer->LinkToWorld (); + tracer->LinkToWorld (&ctx); tracer->flags2 = ActorFlags2::FromInt (special2); } } diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 13a347ef2c..4136ec3313 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -1454,10 +1454,11 @@ enum CM_Flags CMF_OFFSETPITCH = 32, CMF_SAVEPITCH = 64, - CMF_ABSOLUTEANGLE = 128 + CMF_ABSOLUTEANGLE = 128, + CMF_BADPITCH = 256 }; -DEFINE_ACTION_FUNCTION(AActor, A_CustomMissile) +DEFINE_ACTION_FUNCTION(AActor, A_SpawnProjectile) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (ti, AActor); @@ -1525,6 +1526,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomMissile) } missilespeed = fabs(Pitch.Cos() * missile->Speed); missile->Vel.Z = Pitch.Sin() * missile->Speed; + if (!(flags & CMF_BADPITCH)) missile->Vel.Z *= -1; } else { @@ -1831,7 +1833,7 @@ static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp, b // Aim for the base of the puff as that's where blood puffs will spawn... roughly. A_Face(proj, puff, 0., 0., 0., 0., 1); - proj->Vel3DFromAngle(-proj->Angles.Pitch, proj->Speed); + proj->Vel3DFromAngle(proj->Angles.Pitch, proj->Speed); if (!temp) { @@ -1986,7 +1988,7 @@ enum FP_Flags FPF_TRANSFERTRANSLATION = 2, FPF_NOAUTOAIM = 4, }; -DEFINE_ACTION_FUNCTION(AStateProvider, A_FireCustomMissile) +DEFINE_ACTION_FUNCTION(AStateProvider, A_FireProjectile) { PARAM_ACTION_PROLOGUE(AStateProvider); PARAM_CLASS (ti, AActor); @@ -2300,7 +2302,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomRailgun) // We probably won't hit the target, but aim at it anyway so we don't look stupid. DVector2 xydiff = self->Vec2To(self->target); double zdiff = self->target->Center() - self->Center() - self->Floorclip; - self->Angles.Pitch = VecToAngle(xydiff.Length(), zdiff); + self->Angles.Pitch = -VecToAngle(xydiff.Length(), zdiff); } // Let the aim trail behind the player if (aim) @@ -5227,12 +5229,13 @@ void A_Weave(AActor *self, int xyspeed, int zspeed, double xydist, double zdist) } else { - self->UnlinkFromWorld (); + FLinkContext ctx; + self->UnlinkFromWorld (&ctx); self->flags |= MF_NOBLOCKMAP; // We need to do portal offsetting here explicitly, because SetXY cannot do that. newpos -= self->Pos().XY(); self->SetXY(self->Vec2Offset(newpos.X, newpos.Y)); - self->LinkToWorld (); + self->LinkToWorld (&ctx); } self->WeaveIndexXY = weaveXY; } @@ -6688,10 +6691,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_FaceMovementDirection) { DAngle current = mobj->Angles.Pitch; const DVector2 velocity = mobj->Vel.XY(); - DAngle pitch = VecToAngle(velocity.Length(), mobj->Vel.Z); + DAngle pitch = -VecToAngle(velocity.Length(), mobj->Vel.Z); if (pitchlimit > 0) { - DAngle pdelta = deltaangle(-current, pitch); + DAngle pdelta = deltaangle(current, pitch); if (fabs(pdelta) > pitchlimit) { @@ -6860,17 +6863,18 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetSize) double oldradius = self->radius; double oldheight = self->Height; - self->UnlinkFromWorld(); + FLinkContext ctx; + self->UnlinkFromWorld(&ctx); self->radius = newradius; self->Height = newheight; - self->LinkToWorld(); + self->LinkToWorld(&ctx); if (testpos && !P_TestMobjLocation(self)) { - self->UnlinkFromWorld(); + self->UnlinkFromWorld(&ctx); self->radius = oldradius; self->Height = oldheight; - self->LinkToWorld(); + self->LinkToWorld(&ctx); ACTION_RETURN_BOOL(false); } diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 9aa178e64d..102142d38f 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1545,7 +1545,7 @@ dopain: target->SetState (target->SeeState); } } - else if (source != target->target && target->OkayToSwitchTarget (source)) + else if ((damage > 0 || fakedPain) && source != target->target && target->OkayToSwitchTarget (source)) { // Target actor is not intent on another actor, // so make him chase after source diff --git a/src/p_local.h b/src/p_local.h index ef702e0188..25b465d26a 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -245,10 +245,6 @@ AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable=false, // -// If "floatok" true, move would be ok -// if within "tmfloorz - tmceilingz". -extern msecnode_t *sector_list; // phares 3/16/98 - struct spechit_t { line_t *line; @@ -395,11 +391,12 @@ enum int P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance, FName damageType, int flags, int fulldamagedistance=0); -void P_DelSector_List(); void P_DelSeclist(msecnode_t *); // phares 3/16/98 msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist); msecnode_t* P_DelSecnode(msecnode_t *, msecnode_t *sector_t::*head); -void P_CreateSecNodeList(AActor*); // phares 3/14/98 +msecnode_t *P_CreateSecNodeList(AActor *thing, msecnode_t *sector_list); +void P_LinkRenderSectors(AActor*); +void P_UnlinkRenderSectors(AActor*); double P_GetMoveFactor(const AActor *mo, double *frictionp); // phares 3/6/98 double P_GetFriction(const AActor *mo, double *frictionfactor); diff --git a/src/p_map.cpp b/src/p_map.cpp index f889069f18..9dcd165c2f 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -24,6 +24,7 @@ #include #include +#include #include "templates.h" @@ -81,9 +82,6 @@ static FRandom pr_crunch("DoCrunch"); TArray spechit; TArray portalhit; -// Temporary holder for thing_sectorlist threads -msecnode_t* sector_list = NULL; // phares 3/16/98 - //========================================================================== // // FindRefPoint @@ -2389,10 +2387,11 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, FLinePortal *port = ld->getPortal(); if (port->mType == PORTT_LINKED) { - thing->UnlinkFromWorld(); + FLinkContext ctx; + thing->UnlinkFromWorld(&ctx); thing->SetXY(tm.pos + port->mDisplacement); thing->Prev += port->mDisplacement; - thing->LinkToWorld(); + thing->LinkToWorld(&ctx); P_FindFloorCeiling(thing); portalcrossed = true; tm.portalstep = false; @@ -2413,11 +2412,12 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, thing->flags6 &= ~MF6_INTRYMOVE; return false; } - thing->UnlinkFromWorld(); + FLinkContext ctx; + thing->UnlinkFromWorld(&ctx); thing->SetXYZ(pos); P_TranslatePortalVXVY(ld, thing->Vel.X, thing->Vel.Y); P_TranslatePortalAngle(ld, thing->Angles.Yaw); - thing->LinkToWorld(); + thing->LinkToWorld(&ctx); P_FindFloorCeiling(thing); thing->ClearInterpolation(); portalcrossed = true; @@ -2458,7 +2458,8 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, if (!portalcrossed) { // the move is ok, so link the thing into its new position - thing->UnlinkFromWorld(); + FLinkContext ctx; + thing->UnlinkFromWorld(&ctx); oldsector = thing->Sector; thing->floorz = tm.floorz; @@ -2471,7 +2472,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, thing->ceilingsector = tm.ceilingsector; thing->SetXY(pos); - thing->LinkToWorld(); + thing->LinkToWorld(&ctx); } if (thing->flags2 & MF2_FLOORCLIP) @@ -2564,13 +2565,14 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, // If the actor stepped through a ceiling portal we need to reacquire the actual position info after the transition if (tm.portalstep) { + FLinkContext ctx; DVector3 oldpos = thing->Pos(); - thing->UnlinkFromWorld(); + thing->UnlinkFromWorld(&ctx); thing->SetXYZ(thing->PosRelative(thing->Sector->GetOppositePortalGroup(sector_t::ceiling))); thing->Prev = thing->Pos() - oldpos; thing->Sector = P_PointInSector(thing->Pos()); thing->PrevPortalGroup = thing->Sector->PortalGroup; - thing->LinkToWorld(); + thing->LinkToWorld(&ctx); P_FindFloorCeiling(thing); } @@ -4920,10 +4922,10 @@ void P_RailAttack(FRailParams *p) } AActor *source = p->source; - DAngle pitch = -source->Angles.Pitch + p->pitchoffset; + DAngle pitch = source->Angles.Pitch + p->pitchoffset; DAngle angle = source->Angles.Yaw + p->angleoffset; - DVector3 vec(DRotator(pitch, angle, angle)); + DVector3 vec(DRotator(-pitch, angle, angle)); double shootz = source->Center() - source->FloatSpeed + p->offset_z; if (!(p->flags & RAF_CENTERZ)) @@ -6531,23 +6533,6 @@ msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead) return NULL; } // phares 3/13/98 -//============================================================================= -// -// P_DelSector_List -// -// Deletes the sector_list and NULLs it. -// -//============================================================================= - -void P_DelSector_List() -{ - if (sector_list != NULL) - { - P_DelSeclist(sector_list); - sector_list = NULL; - } -} - //============================================================================= // // P_DelSeclist @@ -6571,7 +6556,7 @@ void P_DelSeclist(msecnode_t *node) // //============================================================================= -void P_CreateSecNodeList(AActor *thing) +msecnode_t *P_CreateSecNodeList(AActor *thing, msecnode_t *sector_list) { msecnode_t *node; @@ -6637,6 +6622,103 @@ void P_CreateSecNodeList(AActor *thing) node = node->m_tnext; } } + return sector_list; +} + + +//============================================================================= +// +// P_LinkRenderSectors +// +// Alters/creates the list of touched sectors for thing's render radius. +// +//============================================================================= + +void P_LinkRenderSectors(AActor* thing) +{ + // if this thing has RenderStyle None, don't link it anywhere. + if (thing->renderradius >= 0) + { + FBoundingBox box(thing->X(), thing->Y(), std::max(thing->radius, thing->renderradius)); + FBlockLinesIterator it(box); + line_t *ld; + + // add to surrounding sectors + while ((ld = it.Next())) + { + if (!box.inRange(ld) || box.BoxOnLineSide(ld) != -1) + continue; + + // + // create necessary lists. + if (!thing->touching_render_sectors) thing->touching_render_sectors = new std::forward_list(); + + // + if (ld->frontsector != thing->Sector) + { + if (std::find(thing->touching_render_sectors->begin(), thing->touching_render_sectors->end(), ld->frontsector) == thing->touching_render_sectors->end()) + thing->touching_render_sectors->push_front(ld->frontsector); + if (!ld->frontsector->touching_render_things) ld->frontsector->touching_render_things = new std::forward_list(); + ld->frontsector->touching_render_things->push_front(thing); + } + + if (ld->backsector && ld->backsector != thing->Sector) + { + if (std::find(thing->touching_render_sectors->begin(), thing->touching_render_sectors->end(), ld->backsector) == thing->touching_render_sectors->end()) + thing->touching_render_sectors->push_front(ld->backsector); + if (!ld->backsector->touching_render_things) ld->backsector->touching_render_things = new std::forward_list(); + ld->backsector->touching_render_things->push_front(thing); + } + } + } + + // add to own sector + if (!thing->Sector->touching_render_things) thing->Sector->touching_render_things = new std::forward_list(); + thing->Sector->touching_render_things->push_front(thing); +} + + +//============================================================================= +// +// P_UnlinkRenderSectors +// +// Reverses P_LinkRenderSectors. +// +//============================================================================= + +void P_UnlinkRenderSectors(AActor* thing) +{ + if (thing->renderradius >= 0) + { + if (thing->touching_render_sectors) + { + for (auto sec : *thing->touching_render_sectors) + { + if (sec->touching_render_things) + { + sec->touching_render_things->remove(thing); + if (sec->touching_render_things->empty()) + { + delete sec->touching_render_things; + sec->touching_render_things = NULL; + } + } + } + + delete thing->touching_render_sectors; + thing->touching_render_sectors = NULL; + } + } + + if (thing->Sector->touching_render_things) + { + thing->Sector->touching_render_things->remove(thing); + if (thing->Sector->touching_render_things->empty()) + { + delete thing->Sector->touching_render_things; + thing->Sector->touching_render_things = NULL; + } + } } diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index d676e966cc..d7d5fd6588 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -242,9 +242,9 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef, co // //========================================================================== -void AActor::UnlinkFromWorld () +void AActor::UnlinkFromWorld (FLinkContext *ctx) { - sector_list = NULL; + if (ctx != nullptr) ctx->sector_list = nullptr; if (!(flags & MF_NOSECTOR)) { // invisible things don't need to be in sector list @@ -275,8 +275,11 @@ void AActor::UnlinkFromWorld () // If this Thing is being removed entirely, then the calling // routine will clear out the nodes in sector_list. - sector_list = touching_sectorlist; + if (ctx != nullptr) ctx->sector_list = touching_sectorlist; + else P_DelSeclist(touching_sectorlist); touching_sectorlist = NULL; //to be restored by P_SetThingPosition + + P_UnlinkRenderSectors(this); } } @@ -388,7 +391,7 @@ bool AActor::FixMapthingPos() DEFINE_ACTION_FUNCTION(AActor, UnlinkFromWorld) { PARAM_SELF_PROLOGUE(AActor); - self->UnlinkFromWorld(); + self->UnlinkFromWorld(nullptr); // fixme return 0; } @@ -401,7 +404,7 @@ DEFINE_ACTION_FUNCTION(AActor, UnlinkFromWorld) // //========================================================================== -void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector) +void AActor::LinkToWorld(FLinkContext *ctx, bool spawningmapthing, sector_t *sector) { bool spawning = spawningmapthing; @@ -453,9 +456,9 @@ void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector) // When a node is deleted, its sector links (the links starting // at sector_t->touching_thinglist) are broken. When a node is // added, new sector links are created. - P_CreateSecNodeList(this); - touching_sectorlist = sector_list; // Attach to thing - sector_list = NULL; // clear for next time + touching_sectorlist = P_CreateSecNodeList(this, ctx != nullptr? ctx->sector_list : nullptr); // Attach to thing + + P_LinkRenderSectors(this); } @@ -518,15 +521,16 @@ void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector) DEFINE_ACTION_FUNCTION(AActor, LinkToWorld) { PARAM_SELF_PROLOGUE(AActor); - self->LinkToWorld(); + self->LinkToWorld(nullptr); // fixme return 0; } void AActor::SetOrigin(double x, double y, double z, bool moving) { - UnlinkFromWorld (); + FLinkContext ctx; + UnlinkFromWorld (&ctx); SetXYZ(x, y, z); - LinkToWorld (); + LinkToWorld (&ctx); P_FindFloorCeiling(this, FFCF_ONLYSPAWNPOS); if (!moving) ClearInterpolation(); } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index b527bf6813..1955f6b4ef 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -204,6 +204,7 @@ DEFINE_FIELD(AActor, ceilingsector) DEFINE_FIELD(AActor, ceilingpic) DEFINE_FIELD(AActor, Height) DEFINE_FIELD(AActor, radius) +DEFINE_FIELD(AActor, renderradius) DEFINE_FIELD(AActor, projectilepassheight) DEFINE_FIELD(AActor, tics) DEFINE_FIELD_NAMED(AActor, state, curstate) // clashes with type 'state'. @@ -373,6 +374,7 @@ void AActor::Serialize(FSerializer &arc) A("floorsector", floorsector) A("ceilingsector", ceilingsector) A("radius", radius) + A("renderradius", renderradius) A("height", Height) A("ppassheight", projectilepassheight) A("vel", Vel) @@ -510,7 +512,9 @@ void AActor::Serialize(FSerializer &arc) void AActor::PostSerialize() { touching_sectorlist = NULL; - LinkToWorld(false, Sector); + if (touching_render_sectors) delete touching_render_sectors; + touching_render_sectors = NULL; + LinkToWorld(nullptr, false, Sector); AddToHash(); if (player) @@ -3686,12 +3690,13 @@ DVector3 AActor::GetPortalTransition(double byoffset, sector_t **pSec) void AActor::CheckPortalTransition(bool islinked) { bool moved = false; + FLinkContext ctx; while (!Sector->PortalBlocksMovement(sector_t::ceiling)) { if (Z() >= Sector->GetPortalPlaneZ(sector_t::ceiling)) { DVector3 oldpos = Pos(); - if (islinked && !moved) UnlinkFromWorld(); + if (islinked && !moved) UnlinkFromWorld(&ctx); SetXYZ(PosRelative(Sector->GetOppositePortalGroup(sector_t::ceiling))); Prev = Pos() - oldpos; Sector = P_PointInSector(Pos()); @@ -3708,7 +3713,7 @@ void AActor::CheckPortalTransition(bool islinked) if (Z() < portalz && floorz < portalz) { DVector3 oldpos = Pos(); - if (islinked && !moved) UnlinkFromWorld(); + if (islinked && !moved) UnlinkFromWorld(&ctx); SetXYZ(PosRelative(Sector->GetOppositePortalGroup(sector_t::floor))); Prev = Pos() - oldpos; Sector = P_PointInSector(Pos()); @@ -3718,7 +3723,7 @@ void AActor::CheckPortalTransition(bool islinked) else break; } } - if (islinked && moved) LinkToWorld(); + if (islinked && moved) LinkToWorld(&ctx); } // @@ -3781,11 +3786,12 @@ void AActor::Tick () if (!Vel.isZero() || !(flags & MF_NOBLOCKMAP)) { - UnlinkFromWorld(); + FLinkContext ctx; + UnlinkFromWorld(&ctx); flags |= MF_NOBLOCKMAP; SetXYZ(Vec3Offset(Vel)); CheckPortalTransition(false); - LinkToWorld(); + LinkToWorld(&ctx); } } else @@ -4544,11 +4550,12 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a actor->frame = st->GetFrame(); actor->renderflags = (actor->renderflags & ~RF_FULLBRIGHT) | ActorRenderFlags::FromInt (st->GetFullbright()); actor->touching_sectorlist = NULL; // NULL head of sector list // phares 3/13/98 + actor->touching_render_sectors = NULL; if (G_SkillProperty(SKILLP_FastMonsters) && actor->GetClass()->FastSpeed >= 0) actor->Speed = actor->GetClass()->FastSpeed; // set subsector and/or block links - actor->LinkToWorld (SpawningMapThing); + actor->LinkToWorld (nullptr, SpawningMapThing); actor->ClearInterpolation(); actor->dropoffz = actor->floorz = actor->Sector->floorplane.ZatPoint(pos); @@ -4925,12 +4932,9 @@ void AActor::Destroy () RemoveFromHash (); // unlink from sector and block lists - UnlinkFromWorld (); + UnlinkFromWorld (nullptr); flags |= MF_NOSECTOR|MF_NOBLOCKMAP; - // Delete all nodes on the current sector_list phares 3/16/98 - P_DelSector_List(); - // Transform any playing sound into positioned, non-actor sounds. S_RelinkSound (this, NULL); @@ -6321,7 +6325,7 @@ bool P_CheckMissileSpawn (AActor* th, double maxdist) // [RH] Don't explode ripping missiles that spawn inside something if (th->BlockingMobj == NULL || !(th->flags2 & MF2_RIP) || (th->BlockingMobj->flags5 & MF5_DONTRIP)) { - // If this is a monster spawned by A_CustomMissile subtract it from the counter. + // If this is a monster spawned by A_SpawnProjectile subtract it from the counter. th->ClearCounters(); // [RH] Don't explode missiles that spawn on top of horizon lines if (th->BlockingLine != NULL && th->BlockingLine->special == Line_Horizon) @@ -7481,9 +7485,10 @@ void AActor::RestoreSpecialPosition() // Move item back to its original location DVector2 sp = SpawnPoint; - UnlinkFromWorld(); + FLinkContext ctx; + UnlinkFromWorld(&ctx); SetXY(sp); - LinkToWorld(true); + LinkToWorld(&ctx, true); SetZ(Sector->floorplane.ZatPoint(sp)); P_FindFloorCeiling(this, FFCF_ONLYSPAWNPOS | FFCF_NOPORTALS); // no portal checks here so that things get spawned in this sector. diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 11aef9d8db..7c663508b1 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1512,6 +1512,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex) ss->thinglist = NULL; ss->touching_thinglist = NULL; // phares 3/14/98 ss->render_thinglist = NULL; + ss->touching_render_things = NULL; ss->seqType = defSeqType; ss->SeqName = NAME_None; ss->nextsec = -1; //jff 2/26/98 add fields to support locking out diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index c1a64f84b7..2e335f4f07 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1297,6 +1297,7 @@ public: sec->thinglist = NULL; sec->touching_thinglist = NULL; // phares 3/14/98 sec->render_thinglist = NULL; + sec->touching_render_things = NULL; sec->seqType = (level.flags & LEVEL_SNDSEQTOTALCTRL) ? 0 : -1; sec->nextsec = -1; //jff 2/26/98 add fields to support locking out sec->prevsec = -1; // stair retriggering until build completes diff --git a/src/p_user.cpp b/src/p_user.cpp index 47c64d0637..40a3cb2f6d 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2939,7 +2939,8 @@ void P_UnPredictPlayer () // could cause it to change during prediction. player->camera = savedcamera; - act->UnlinkFromWorld(); + FLinkContext ctx; + act->UnlinkFromWorld(&ctx); memcpy(&act->snext, PredictionActorBackup, sizeof(APlayerPawn) - ((BYTE *)&act->snext - (BYTE *)act)); // The blockmap ordering needs to remain unchanged, too. @@ -2968,7 +2969,7 @@ void P_UnPredictPlayer () } // Destroy old refrences - msecnode_t *node = sector_list; + msecnode_t *node = ctx.sector_list; while (node) { node->m_thing = NULL; @@ -2976,22 +2977,23 @@ void P_UnPredictPlayer () } // Make the sector_list match the player's touching_sectorlist before it got predicted. - P_DelSeclist(sector_list); - sector_list = NULL; + P_DelSeclist(ctx.sector_list); + ctx.sector_list = NULL; for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;) { - sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, sector_list, PredictionTouchingSectorsBackup[i]->touching_thinglist); + ctx.sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, ctx.sector_list, PredictionTouchingSectorsBackup[i]->touching_thinglist); } - act->touching_sectorlist = sector_list; // Attach to thing - sector_list = NULL; // clear for next time + act->touching_sectorlist = ctx.sector_list; // Attach to thing + ctx.sector_list = NULL; // clear for next time - node = sector_list; + // Huh??? + node = ctx.sector_list; while (node) { if (node->m_thing == NULL) { - if (node == sector_list) - sector_list = node->m_tnext; + if (node == ctx.sector_list) + ctx.sector_list = node->m_tnext; node = P_DelSecnode(node, §or_t::touching_thinglist); } else diff --git a/src/portal.cpp b/src/portal.cpp index 156643cfba..121b05e19f 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -1140,8 +1140,9 @@ void P_CreateLinkedPortals() P_CollectConnectedGroups(actor->Sector->PortalGroup, actor->Pos(), actor->Top(), actor->radius, check); if (check.Size() > 0) { - actor->UnlinkFromWorld(); - actor->LinkToWorld(); + FLinkContext ctx; + actor->UnlinkFromWorld(&ctx); + actor->LinkToWorld(&ctx); } } } diff --git a/src/r_defs.h b/src/r_defs.h index 6efca5cde8..3b064c7607 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -23,6 +23,7 @@ #ifndef __R_DEFS_H__ #define __R_DEFS_H__ +#include #include "doomdef.h" #include "templates.h" #include "memarena.h" @@ -1048,6 +1049,7 @@ public: // thinglist is a subset of touching_thinglist struct msecnode_t *touching_thinglist; // phares 3/14/98 struct msecnode_t *render_thinglist; // for cross-portal rendering. + std::forward_list* touching_render_things; // this is used to allow wide things to be rendered not only from their main sector. double gravity; // [RH] Sector gravity (1.0 is normal) FNameNoInit damagetype; // [RH] Means-of-death for applied damage diff --git a/src/r_things.cpp b/src/r_things.cpp index a1ace0d49c..8d326b319a 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1217,7 +1217,6 @@ static void R_ProjectWallSprite(AActor *thing, const DVector3 &pos, FTextureID p // [RH] Save which side of heightsec sprite is on here. void R_AddSprites (sector_t *sec, int lightlevel, int fakeside) { - AActor *thing; F3DFloor *fakeceiling = NULL; F3DFloor *fakefloor = NULL; @@ -1225,7 +1224,7 @@ void R_AddSprites (sector_t *sec, int lightlevel, int fakeside) // A sector might have been split into several // subsectors during BSP building. // Thus we check whether it was already added. - if (sec->thinglist == NULL || sec->validcount == validcount) + if (sec->touching_render_things == NULL || sec->validcount == validcount) return; // Well, now it will be done. @@ -1234,8 +1233,11 @@ void R_AddSprites (sector_t *sec, int lightlevel, int fakeside) spriteshade = LIGHT2SHADE(lightlevel + r_actualextralight); // Handle all things in sector. - for (thing = sec->thinglist; thing; thing = thing->snext) + for (auto thing : *sec->touching_render_things) { + if (thing->validcount == validcount) continue; + thing->validcount = validcount; + FIntCVar *cvar = thing->GetClass()->distancecheck; if (cvar != NULL && *cvar >= 0) { diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 8e57506606..6a1bc8717d 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -7493,7 +7493,7 @@ isresolved: else { // Todo: If this is a qualified call to a parent class function, let it through (but this needs to disable virtual calls later.) - ScriptPosition.Message(MSG_ERROR, "Qualified member call to parent class not yet implemented\n", cls->TypeName.GetChars(), MethodName.GetChars()); + ScriptPosition.Message(MSG_ERROR, "Qualified member call to parent class %s::%s is not yet implemented\n", cls->TypeName.GetChars(), MethodName.GetChars()); delete this; return nullptr; } @@ -7897,7 +7897,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) // For a reference argument the types must match 100%. if (type != ArgList[i]->ValueType) { - ScriptPosition.Message(MSG_ERROR, "Type mismatch in reference argument", Function->SymbolName.GetChars()); + ScriptPosition.Message(MSG_ERROR, "Type mismatch in reference argument %s", Function->SymbolName.GetChars()); x = nullptr; } else @@ -8346,7 +8346,7 @@ FxExpression *FxGetDefaultByType::Resolve(FCompileContext &ctx) { // this is the ugly case. We do not know what we have and cannot do proper type casting. // For now error out and let this case require explicit handling on the user side. - ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type", static_cast(Self)->GetValue().GetString().GetChars()); + ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type, but got %s", static_cast(Self)->GetValue().GetString().GetChars()); delete this; return nullptr; } @@ -9511,7 +9511,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) /* lax */ // Since this happens in released WADs it must pass without a terminal error... :( ScriptPosition.Message(MSG_OPTERROR, - "Unknown class name '%s'", + "Unknown class name '%s' of type '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); } else diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 5d2d251a9f..355cc87f31 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -272,7 +272,7 @@ static void CheckForUnsafeStates(PClassActor *obj) // If an unsafe function (i.e. one that accesses user variables) is being detected, print a warning once and remove the bogus function. We may not call it because that would inevitably crash. auto owner = FState::StaticFindStateOwner(state); GetStateSource(state).Message(MSG_ERROR, TEXTCOLOR_RED "Unsafe state call in state %s.%d which accesses user variables, reached by %s.%s.\n", - owner->TypeName.GetChars(), state - owner->OwnedStates, obj->TypeName.GetChars(), FName(*test).GetChars()); + owner->TypeName.GetChars(), int(state - owner->OwnedStates), obj->TypeName.GetChars(), FName(*test).GetChars()); } state = state->NextState; } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 9eb050a83e..27b7ab2d33 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -216,9 +216,10 @@ bool ModActorFlag(AActor *actor, FString &flagname, bool set, bool printerror) // If these 2 flags get changed we need to update the blockmap and sector links. bool linkchange = flagp == &actor->flags && (fd->flagbit == MF_NOBLOCKMAP || fd->flagbit == MF_NOSECTOR); - if (linkchange) actor->UnlinkFromWorld(); + FLinkContext ctx; + if (linkchange) actor->UnlinkFromWorld(&ctx); ModActorFlag(actor, fd, set); - if (linkchange) actor->LinkToWorld(); + if (linkchange) actor->LinkToWorld(&ctx); } if (actor->CountsAsKill() && actor->health > 0) ++level.total_monsters; @@ -525,7 +526,7 @@ DEFINE_PROPERTY(skip_super, 0, Actor) if (info->Size != actorclass->Size) { bag.ScriptPosition.Message(MSG_OPTERROR, - "'skip_super' is only allowed in subclasses of AActor with no additional fields and will be ignored.", info->TypeName.GetChars()); + "'skip_super' is only allowed in subclasses of AActor with no additional fields and will be ignored in type %s.", info->TypeName.GetChars()); return; } if (bag.StateSet) @@ -713,6 +714,15 @@ DEFINE_PROPERTY(radius, F, Actor) defaults->radius = id; } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(renderradius, F, Actor) +{ + PROP_DOUBLE_PARM(id, 0); + defaults->renderradius = id; +} + //========================================================================== // //========================================================================== diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index c4c5248171..9684ec9246 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1323,7 +1323,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel } else if (hasnativechildren) { - Error(field, "Cannot add field %s to %s. %s has native children which means it size may not change.", type->TypeName.GetChars(), fd->FieldSize, FName(name->Name).GetChars()); + Error(field, "Cannot add field %s to %s. %s has native children which means it size may not change.", FName(name->Name).GetChars(), type->TypeName.GetChars(), type->TypeName.GetChars()); } else { diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index f12e554bba..d9e60f2484 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -38,6 +38,8 @@ #include "zscript/shared/fastprojectile.txt" #include "zscript/shared/dynlights.txt" +#include "zscript/compatibility.txt" + #include "zscript/doom/doomplayer.txt" #include "zscript/doom/possessed.txt" #include "zscript/doom/doomimp.txt" diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 0d264580a8..2ced709aee 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -45,6 +45,7 @@ class Actor : Thinker native native TextureID ceilingpic; native double Height; native readonly double Radius; + native readonly double RenderRadius; native double projectilepassheight; native int tics; native readonly State CurState; @@ -201,6 +202,7 @@ class Actor : Thinker native Health DEFAULT_HEALTH; Reactiontime 8; Radius 20; + RenderRadius 0; Height 16; Mass 100; RenderStyle 'Normal'; @@ -691,7 +693,7 @@ class Actor : Thinker native deprecated native void A_StopSoundEx(name slot); native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10); native action state A_Jump(int chance, statelabel label, ...); - native void A_CustomMissile(class missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET); + native void A_SpawnProjectile(class missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET); native void A_CustomBulletAttack(double spread_xy, double spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", double range = 0, int flags = 0, int ptr = AAPTR_TARGET, class missile = null, double Spawnheight = 32, double Spawnofs_xy = 0); native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = 0, color color2 = 0, int flags = 0, int aim = 0, double maxdiff = 0, class pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class spawnclass = null, double spawnofs_z = 0, int spiraloffset = 270, int limit = 0); native bool A_SetInventory(class itemtype, int amount, int ptr = AAPTR_DEFAULT, bool beyondMax = false); diff --git a/wadsrc/static/zscript/chex/chexweapons.txt b/wadsrc/static/zscript/chex/chexweapons.txt index a4c862d64c..5bf6fe7575 100644 --- a/wadsrc/static/zscript/chex/chexweapons.txt +++ b/wadsrc/static/zscript/chex/chexweapons.txt @@ -77,7 +77,7 @@ class ZorchPropulsor : RocketLauncher { Fire: MISG B 8 A_GunFlash; - MISG B 12 A_FireCustomMissile("PropulsorMissile"); + MISG B 12 A_FireProjectile("PropulsorMissile"); MISG B 0 A_ReFire; Goto Ready; } @@ -107,7 +107,7 @@ class PhasingZorcher : PlasmaRifle { Fire: PLSG A 0 A_GunFlash; - PLSG A 3 A_FireCustomMissile("PhaseZorchMissile"); + PLSG A 3 A_FireProjectile("PhaseZorchMissile"); PLSG B 20 A_ReFire; Goto Ready; Flash: @@ -143,7 +143,7 @@ class LAZDevice : BFG9000 Fire: BFGG A 20 A_BFGsound; BFGG B 10 A_GunFlash; - BFGG B 10 A_FireCustomMissile("LAZBall"); + BFGG B 10 A_FireProjectile("LAZBall"); BFGG B 20 A_ReFire; Goto Ready; } diff --git a/wadsrc/static/zscript/compatibility.txt b/wadsrc/static/zscript/compatibility.txt new file mode 100644 index 0000000000..9334bd6196 --- /dev/null +++ b/wadsrc/static/zscript/compatibility.txt @@ -0,0 +1,18 @@ +// This file contains compatibility wrappers for DECORATE functions with bad parameters. + +extend class Actor +{ + deprecated void A_CustomMissile(class missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET) + { + A_SpawnProjectile(missiletype, spawnheight, spawnofs_xy, angle, flags|CMF_BADPITCH, pitch, ptr); + } +} + +extend class StateProvider +{ + deprecated action void A_FireCustomMissile(class missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0) + { + A_FireProjectile(missiletype, angle, useammo, spawnofs_xy, spawnheight, flags, -pitch); + } +} + diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 6f57b4222e..1d2064aa1a 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -45,7 +45,7 @@ enum EBFGSprayFlags BFGF_MISSILEORIGIN = 2, }; -// Flags for A_CustomMissile +// Flags for A_SpawnProjectile enum ECustomMissileFlags { CMF_AIMOFFSET = 1, @@ -56,6 +56,7 @@ enum ECustomMissileFlags CMF_OFFSETPITCH = 32, CMF_SAVEPITCH = 64, CMF_ABSOLUTEANGLE = 128, + CMF_BADPITCH = 256, // for compatibility handling only - avoid! }; // Flags for A_CustomBulletAttack diff --git a/wadsrc/static/zscript/doom/archvile.txt b/wadsrc/static/zscript/doom/archvile.txt index 9faa804954..a19e5c705c 100644 --- a/wadsrc/static/zscript/doom/archvile.txt +++ b/wadsrc/static/zscript/doom/archvile.txt @@ -125,25 +125,26 @@ extend class Actor void A_VileAttack(sound snd = "vile/stop", int initialdmg = 20, int blastdmg = 70, int blastradius = 70, double thrust = 1.0, name damagetype = "Fire", int flags = 0) { - if (target) + Actor targ = target; + if (targ) { A_FaceTarget(); - if (!CheckSight(target, 0)) return; + if (!CheckSight(targ, 0)) return; A_PlaySound(snd, CHAN_WEAPON); - int newdam = target.DamageMobj (self, self, initialdmg, (flags & VAF_DMGTYPEAPPLYTODIRECT)? damagetype : 'none'); + int newdam = targ.DamageMobj (self, self, initialdmg, (flags & VAF_DMGTYPEAPPLYTODIRECT)? damagetype : 'none'); - TraceBleed (newdam > 0 ? newdam : initialdmg, target); + TraceBleed (newdam > 0 ? newdam : initialdmg, targ); Actor fire = tracer; if (fire) { // move the fire between the vile and the player - fire.SetOrigin(target.Vec3Angle(-24., angle, 0), true); + fire.SetOrigin(targ.Vec3Angle(-24., angle, 0), true); fire.A_Explode(blastdmg, blastradius, XF_NOSPLASH, false, 0, 0, 0, "BulletPuff", damagetype); } - if (!target.bDontThrust) + if (!targ.bDontThrust) { - target.Vel.z = thrust * 1000 / max(1, target.Mass); + targ.Vel.z = thrust * 1000 / max(1, targ.Mass); } } } diff --git a/wadsrc/static/zscript/heretic/snake.txt b/wadsrc/static/zscript/heretic/snake.txt index 613559a86c..15ae342aa6 100644 --- a/wadsrc/static/zscript/heretic/snake.txt +++ b/wadsrc/static/zscript/heretic/snake.txt @@ -28,9 +28,9 @@ class Snake : Actor Loop; Missile: SNKE FF 5 A_FaceTarget; - SNKE FFF 4 A_CustomMissile("SnakeProjA", 32, 0, 0, CMF_CHECKTARGETDEAD); + SNKE FFF 4 A_SpawnProjectile("SnakeProjA", 32, 0, 0, CMF_CHECKTARGETDEAD); SNKE FFF 5 A_FaceTarget; - SNKE F 4 A_CustomMissile("SnakeProjB", 32, 0, 0, CMF_CHECKTARGETDEAD); + SNKE F 4 A_SpawnProjectile("SnakeProjB", 32, 0, 0, CMF_CHECKTARGETDEAD); Goto See; Pain: SNKE E 3; diff --git a/wadsrc/static/zscript/heretic/weaponblaster.txt b/wadsrc/static/zscript/heretic/weaponblaster.txt index 8f4756b5b6..612e630c0b 100644 --- a/wadsrc/static/zscript/heretic/weaponblaster.txt +++ b/wadsrc/static/zscript/heretic/weaponblaster.txt @@ -87,7 +87,7 @@ class BlasterPowered : Blaster Fire: BLSR BC 0; Hold: - BLSR D 3 A_FireCustomMissile("BlasterFX1"); + BLSR D 3 A_FireProjectile("BlasterFX1"); BLSR CB 4; BLSR A 0 A_ReFire; Goto Ready; diff --git a/wadsrc/static/zscript/hexen/centaur.txt b/wadsrc/static/zscript/hexen/centaur.txt index f8c8e2c3d3..abf2f19d2f 100644 --- a/wadsrc/static/zscript/hexen/centaur.txt +++ b/wadsrc/static/zscript/hexen/centaur.txt @@ -112,9 +112,9 @@ class CentaurLeader : Centaur { Missile: CENT E 10 A_FaceTarget; - CENT F 8 Bright A_CustomMissile("CentaurFX", 45, 0, 0, CMF_AIMOFFSET); + CENT F 8 Bright A_SpawnProjectile("CentaurFX", 45, 0, 0, CMF_AIMOFFSET); CENT E 10 A_FaceTarget; - CENT F 8 Bright A_CustomMissile("CentaurFX", 45, 0, 0, CMF_AIMOFFSET); + CENT F 8 Bright A_SpawnProjectile("CentaurFX", 45, 0, 0, CMF_AIMOFFSET); Goto See; } } diff --git a/wadsrc/static/zscript/hexen/demons.txt b/wadsrc/static/zscript/hexen/demons.txt index 25e078509b..ef4c96d8d8 100644 --- a/wadsrc/static/zscript/hexen/demons.txt +++ b/wadsrc/static/zscript/hexen/demons.txt @@ -44,7 +44,7 @@ class Demon1 : Actor Missile: DEMN E 5 A_FaceTarget; DEMN F 6 A_FaceTarget; - DEMN G 5 A_CustomMissile("Demon1FX1", 62, 0); + DEMN G 5 A_SpawnProjectile("Demon1FX1", 62, 0); Goto See; Death: DEMN HI 6; @@ -250,7 +250,7 @@ class Demon2 : Demon1 Missile: DEM2 E 5 A_FaceTarget; DEM2 F 6 A_FaceTarget; - DEM2 G 5 A_CustomMissile("Demon2FX1", 62, 0); + DEM2 G 5 A_SpawnProjectile("Demon2FX1", 62, 0); Goto See; Death: DEM2 HI 6; diff --git a/wadsrc/static/zscript/hexen/magewand.txt b/wadsrc/static/zscript/hexen/magewand.txt index 3feb96ae16..9157bdba12 100644 --- a/wadsrc/static/zscript/hexen/magewand.txt +++ b/wadsrc/static/zscript/hexen/magewand.txt @@ -23,7 +23,7 @@ class MWeapWand : MageWeapon Loop; Fire: MWND A 6; - MWND B 6 Bright Offset (0, 48) A_FireCustomMissile ("MageWandMissile"); + MWND B 6 Bright Offset (0, 48) A_FireProjectile ("MageWandMissile"); MWND A 3 Offset (0, 40); MWND A 3 Offset (0, 36) A_ReFire; Goto Ready; diff --git a/wadsrc/static/zscript/hexen/serpent.txt b/wadsrc/static/zscript/hexen/serpent.txt index 6eaafcfd1f..eb26c8c7b9 100644 --- a/wadsrc/static/zscript/hexen/serpent.txt +++ b/wadsrc/static/zscript/hexen/serpent.txt @@ -300,7 +300,7 @@ class SerpentLeader : Serpent States { Missile: - SSPT N 5 A_CustomMissile("SerpentFX", 32, 0); + SSPT N 5 A_SpawnProjectile("SerpentFX", 32, 0); Goto Dive; } } diff --git a/wadsrc/static/zscript/hexen/wraith.txt b/wadsrc/static/zscript/hexen/wraith.txt index 42a81ae6c5..4b90dc4f68 100644 --- a/wadsrc/static/zscript/hexen/wraith.txt +++ b/wadsrc/static/zscript/hexen/wraith.txt @@ -47,7 +47,7 @@ class Wraith : Actor Missile: WRTH E 6 A_FaceTarget; WRTH F 6; - WRTH G 6 A_CustomMissile("WraithFX1"); + WRTH G 6 A_SpawnProjectile("WraithFX1"); Goto See; Death: WRTH I 4; diff --git a/wadsrc/static/zscript/raven/artiegg.txt b/wadsrc/static/zscript/raven/artiegg.txt index f0287048ec..a51e2e1f5d 100644 --- a/wadsrc/static/zscript/raven/artiegg.txt +++ b/wadsrc/static/zscript/raven/artiegg.txt @@ -49,7 +49,7 @@ class ArtiEgg : CustomInventory Use: TNT1 A 0 { - for (double i = -15; i <= 15; i += 7.5) A_FireCustomMissile("EggFX", i, 0, 0, 0, 1); + for (double i = -15; i <= 15; i += 7.5) A_FireProjectile("EggFX", i, false, 0, 0, FPF_AIMATANGLE); } Stop; } @@ -104,7 +104,7 @@ class ArtiPork : CustomInventory Use: TNT1 A 0 { - for (double i = -15; i <= 15; i += 7.5) A_FireCustomMissile("PorkFX", i, 0, 0, 0, 1); + for (double i = -15; i <= 15; i += 7.5) A_FireProjectile("PorkFX", i, false, 0, 0, FPF_AIMATANGLE); } Stop; } diff --git a/wadsrc/static/zscript/shared/bridge.txt b/wadsrc/static/zscript/shared/bridge.txt index ea38796a70..6fb0a99d51 100644 --- a/wadsrc/static/zscript/shared/bridge.txt +++ b/wadsrc/static/zscript/shared/bridge.txt @@ -85,6 +85,7 @@ class InvisibleBridge : Actor native { RenderStyle "None"; Radius 32; + RenderRadius -1; Height 4; +SOLID +NOGRAVITY diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 06e4d75525..6d034e7894 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -84,7 +84,7 @@ class StateProvider : Inventory native action native state A_JumpIfNoAmmo(statelabel label); action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = ""); action native void A_FireBullets(double spread_xy, double spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, double range = 0, class missile = null, double Spawnheight = 32, double Spawnofs_xy = 0); - action native void A_FireCustomMissile(class missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0); + action native void A_FireProjectile(class missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0); action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = 0, color color2 = 0, int flags = 0, double maxdiff = 0, class pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class spawnclass = "none", double spawnofs_z = 0, int spiraloffset = 270, int limit = 0); action native void A_WeaponReady(int flags = 0); action native void A_Lower(); diff --git a/wadsrc/static/zscript/strife/alienspectres.txt b/wadsrc/static/zscript/strife/alienspectres.txt index 39cbc83315..791266cc0d 100644 --- a/wadsrc/static/zscript/strife/alienspectres.txt +++ b/wadsrc/static/zscript/strife/alienspectres.txt @@ -202,7 +202,7 @@ class AlienSpectre2 : AlienSpectre1 { Missile: ALN1 F 4 A_FaceTarget; - ALN1 I 4 A_CustomMissile("SpectralLightningH3", 32, 0); + ALN1 I 4 A_SpawnProjectile("SpectralLightningH3", 32, 0); ALN1 E 4; Goto See+10; } @@ -267,7 +267,7 @@ class AlienSpectre4 : AlienSpectre1 { Missile: ALN1 F 4 A_FaceTarget; - ALN1 I 4 A_CustomMissile("SpectralLightningBigV2", 32, 0); + ALN1 I 4 A_SpawnProjectile("SpectralLightningBigV2", 32, 0); ALN1 E 4; Goto See+10; } @@ -289,7 +289,7 @@ class AlienSpectre5 : AlienSpectre1 { Missile: ALN1 F 4 A_FaceTarget; - ALN1 I 4 A_CustomMissile("SpectralLightningBigBall2", 32, 0); + ALN1 I 4 A_SpawnProjectile("SpectralLightningBigBall2", 32, 0); ALN1 E 4; Goto See+10; } diff --git a/wadsrc/static/zscript/strife/entityboss.txt b/wadsrc/static/zscript/strife/entityboss.txt index daf1a78ee2..a9ec94bb23 100644 --- a/wadsrc/static/zscript/strife/entityboss.txt +++ b/wadsrc/static/zscript/strife/entityboss.txt @@ -265,7 +265,7 @@ class EntitySecond : SpectralMonster Goto See+1; Missile: MNAL W 4 Bright A_FaceTarget; - MNAL U 4 Bright A_CustomMissile("SpectralLightningH3",32,0); + MNAL U 4 Bright A_SpawnProjectile("SpectralLightningH3",32,0); MNAL V 4 Bright A_SentinelBob; Goto See+4; Pain: diff --git a/wadsrc/static/zscript/strife/loremaster.txt b/wadsrc/static/zscript/strife/loremaster.txt index 14571f91c8..cda305d180 100644 --- a/wadsrc/static/zscript/strife/loremaster.txt +++ b/wadsrc/static/zscript/strife/loremaster.txt @@ -55,7 +55,7 @@ class Loremaster : Actor Goto See; Missile: PRST E 4 A_FaceTarget; - PRST F 4 A_CustomMissile("LoreShot", 32, 0); + PRST F 4 A_SpawnProjectile("LoreShot", 32, 0); PRST E 4 A_SentinelBob; Goto See; Death: diff --git a/wadsrc/static/zscript/strife/strifebishop.txt b/wadsrc/static/zscript/strife/strifebishop.txt index b7de186a27..32aacd03a3 100644 --- a/wadsrc/static/zscript/strife/strifebishop.txt +++ b/wadsrc/static/zscript/strife/strifebishop.txt @@ -38,7 +38,7 @@ class StrifeBishop : Actor Loop; Missile: MLDR E 3 A_FaceTarget; - MLDR F 2 Bright A_CustomMissile("BishopMissile", 64, 0, 0, CMF_AIMOFFSET); + MLDR F 2 Bright A_SpawnProjectile("BishopMissile", 64, 0, 0, CMF_AIMOFFSET); Goto See; Pain: MLDR D 1 A_Pain;