diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 6a3371565..11070c0f0 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -1008,6 +1008,7 @@ public: double FloatSpeed; // interaction info + uint32_t ThruBits; FBlockNode *BlockNode; // links in blocks (if needed) struct sector_t *Sector; subsector_t * subsector; diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index 7a7daaabc..9270c3786 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -447,11 +447,14 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi if (th == thing) continue; - double blockdist = th->radius + tmf.thing->radius; - if (fabs(th->X() - cres2.Position.X) >= blockdist || fabs(th->Y() - cres2.Position.Y) >= blockdist) + if ((th->flags2 | tmf.thing->flags2) & MF2_THRUACTORS) continue; - if ((th->flags2 | tmf.thing->flags2) & MF2_THRUACTORS) + if (th->ThruBits & tmf.thing->ThruBits) + continue; + + double blockdist = th->radius + tmf.thing->radius; + if (fabs(th->X() - cres2.Position.X) >= blockdist || fabs(th->Y() - cres2.Position.Y) >= blockdist) continue; if (tmf.thing->flags6 & MF6_THRUSPECIES && tmf.thing->GetSpecies() == th->GetSpecies()) @@ -1301,6 +1304,9 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch if ((thing->flags2 | tm.thing->flags2) & MF2_THRUACTORS) return true; + if (thing->ThruBits & tm.thing->ThruBits) + return true; + if (!((thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE)) || thing->flags6 & MF6_TOUCHY)) return true; // can't hit thing @@ -1994,6 +2000,10 @@ int P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj) { continue; } + if (actor->ThruBits & thing->ThruBits) + { + continue; + } if ((actor->flags6 & MF6_THRUSPECIES) && (thing->GetSpecies() == actor->GetSpecies())) { continue; @@ -4382,6 +4392,8 @@ struct Origin bool MThruSpecies; bool ThruSpecies; bool ThruActors; + bool UseThruBits; + uint32_t ThruBits; }; static ETraceStatus CheckForActor(FTraceResults &res, void *userdata) @@ -4407,6 +4419,9 @@ static ETraceStatus CheckForActor(FTraceResults &res, void *userdata) return TRACE_Skip; } + if (data->UseThruBits && (data->ThruBits & res.Actor->ThruBits)) + return TRACE_Skip; + return TRACE_Stop; } @@ -4482,7 +4497,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, { TData.ThruSpecies = (puffDefaults && (puffDefaults->flags6 & MF6_THRUSPECIES)); TData.ThruActors = (puffDefaults && (puffDefaults->flags2 & MF2_THRUACTORS)); - + TData.UseThruBits = true; // [MC] Because this is a one-hit trace event, we need to spawn the puff, get the species // and destroy it. Assume there is no species unless tempuff isn't NULL. We cannot get // a proper species the same way as puffDefaults flags it appears... @@ -4493,6 +4508,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, if (tempuff != NULL) { TData.PuffSpecies = tempuff->GetSpecies(); + TData.ThruBits = tempuff->ThruBits; tempuff->Destroy(); } } @@ -4500,6 +4516,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, { TData.ThruSpecies = false; TData.ThruActors = false; + TData.UseThruBits = false; } // if the puff uses a non-standard damage type, this will override default, hitscan and melee damage type. // All other explicitly passed damage types (currenty only MDK) will be preserved. @@ -5102,6 +5119,8 @@ struct RailData bool ThruSpecies; bool MThruSpecies; bool ThruActors; + bool UseThruBits; + uint32_t ThruBits; int limit; int count; }; @@ -5131,6 +5150,7 @@ static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata) // 4. THRUGHOST on puff and the GHOST flag on the hit actor if ((data->ThruActors) || + (data->UseThruBits && (data->ThruBits & res.Actor->ThruBits)) || (data->MThruSpecies && res.Actor->GetSpecies() == data->Caller->GetSpecies()) || (data->ThruSpecies && res.Actor->GetSpecies() == data->PuffSpecies) || (data->ThruGhosts && res.Actor->flags3 & MF3_GHOST)) @@ -5228,12 +5248,14 @@ void P_RailAttack(FRailParams *p) rail_data.ThruGhosts = !!(puffDefaults->flags2 & MF2_THRUGHOST); rail_data.ThruSpecies = !!(puffDefaults->flags6 & MF6_THRUSPECIES); rail_data.ThruActors = !!(puffDefaults->flags2 & MF2_THRUACTORS); + rail_data.UseThruBits = true; } else { rail_data.ThruGhosts = false; rail_data.MThruSpecies = false; rail_data.ThruActors = false; + rail_data.UseThruBits = false; } // used as damage inflictor AActor *thepuff = NULL; @@ -5241,6 +5263,9 @@ void P_RailAttack(FRailParams *p) if (puffclass != NULL) thepuff = Spawn(source->Level, puffclass, source->Pos(), ALLOW_REPLACE); rail_data.PuffSpecies = (thepuff != NULL) ? thepuff->GetSpecies() : NAME_None; + if (thepuff) + rail_data.ThruBits = thepuff->ThruBits; + Trace(start, source->Sector, vec, p->distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace, flags, ProcessRailHit, &rail_data); // Hurt anything the trace hit diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index a6a98e94b..870536843 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -349,6 +349,7 @@ void AActor::Serialize(FSerializer &arc) A("spriteangle", SpriteAngle) A("spriterotation", SpriteRotation) ("alternative", alternative) + A("thrubits", ThruBits) A("cameraheight", CameraHeight) A("camerafov", CameraFOV) A("tag", Tag) diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index 41529324e..16fa24c2f 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -1945,6 +1945,7 @@ DEFINE_FIELD(AActor, RenderRequired) DEFINE_FIELD(AActor, friendlyseeblocks) DEFINE_FIELD(AActor, SpawnTime) DEFINE_FIELD(AActor, InventoryID) +DEFINE_FIELD(AActor, ThruBits) DEFINE_FIELD_NAMED(AActor, ViewAngles.Yaw, viewangle) DEFINE_FIELD_NAMED(AActor, ViewAngles.Pitch, viewpitch) DEFINE_FIELD_NAMED(AActor, ViewAngles.Roll, viewroll) diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 4596828c4..1eb9bd2e2 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -90,6 +90,7 @@ class Actor : Thinker native native PlayerInfo Player; native readonly vector3 Pos; native vector3 Prev; + native uint ThruBits; native vector2 SpriteOffset; native double spriteAngle; native double spriteRotation; @@ -337,6 +338,7 @@ class Actor : Thinker native property RenderHidden: RenderHidden; property RenderRequired: RenderRequired; property FriendlySeeBlocks: FriendlySeeBlocks; + property ThruBits: ThruBits; // need some definition work first //FRenderStyle RenderStyle;