mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-14 00:21:34 +00:00
Exported destructible geometry to ZScript
This commit is contained in:
parent
ed3355acc6
commit
a276ebfb08
9 changed files with 400 additions and 40 deletions
|
@ -416,6 +416,20 @@ void E_WorldLineActivated(line_t* line, AActor* actor, int activationType)
|
||||||
handler->WorldLineActivated(line, actor, activationType);
|
handler->WorldLineActivated(line, actor, activationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int E_WorldSectorDamaged(sector_t* sector, AActor* source, int damage, FName damagetype, int part, DVector3 position, bool isradius)
|
||||||
|
{
|
||||||
|
for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next)
|
||||||
|
damage = handler->WorldSectorDamaged(sector, source, damage, damagetype, part, position, isradius);
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
int E_WorldLineDamaged(line_t* line, AActor* source, int damage, FName damagetype, int side, DVector3 position, bool isradius)
|
||||||
|
{
|
||||||
|
for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next)
|
||||||
|
damage = handler->WorldLineDamaged(line, source, damage, damagetype, side, position, isradius);
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
void E_PlayerEntered(int num, bool fromhub)
|
void E_PlayerEntered(int num, bool fromhub)
|
||||||
{
|
{
|
||||||
// this event can happen during savegamerestore. make sure that local handlers don't receive it.
|
// this event can happen during savegamerestore. make sure that local handlers don't receive it.
|
||||||
|
@ -570,6 +584,13 @@ DEFINE_FIELD_X(WorldEvent, FWorldEvent, DamageAngle);
|
||||||
DEFINE_FIELD_X(WorldEvent, FWorldEvent, ActivatedLine);
|
DEFINE_FIELD_X(WorldEvent, FWorldEvent, ActivatedLine);
|
||||||
DEFINE_FIELD_X(WorldEvent, FWorldEvent, ActivationType);
|
DEFINE_FIELD_X(WorldEvent, FWorldEvent, ActivationType);
|
||||||
DEFINE_FIELD_X(WorldEvent, FWorldEvent, ShouldActivate);
|
DEFINE_FIELD_X(WorldEvent, FWorldEvent, ShouldActivate);
|
||||||
|
DEFINE_FIELD_X(WorldEvent, FWorldEvent, DamageSectorPart);
|
||||||
|
DEFINE_FIELD_X(WorldEvent, FWorldEvent, DamageLine);
|
||||||
|
DEFINE_FIELD_X(WorldEvent, FWorldEvent, DamageSector);
|
||||||
|
DEFINE_FIELD_X(WorldEvent, FWorldEvent, DamageLineSide);
|
||||||
|
DEFINE_FIELD_X(WorldEvent, FWorldEvent, DamagePosition);
|
||||||
|
DEFINE_FIELD_X(WorldEvent, FWorldEvent, DamageIsRadius);
|
||||||
|
DEFINE_FIELD_X(WorldEvent, FWorldEvent, NewDamage);
|
||||||
|
|
||||||
DEFINE_FIELD_X(PlayerEvent, FPlayerEvent, PlayerNumber);
|
DEFINE_FIELD_X(PlayerEvent, FPlayerEvent, PlayerNumber);
|
||||||
DEFINE_FIELD_X(PlayerEvent, FPlayerEvent, IsReturn);
|
DEFINE_FIELD_X(PlayerEvent, FPlayerEvent, IsReturn);
|
||||||
|
@ -662,6 +683,8 @@ DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldThingDamaged)
|
||||||
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldThingDestroyed)
|
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldThingDestroyed)
|
||||||
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldLinePreActivated)
|
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldLinePreActivated)
|
||||||
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldLineActivated)
|
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldLineActivated)
|
||||||
|
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldSectorDamaged);
|
||||||
|
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldLineDamaged);
|
||||||
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldLightning)
|
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldLightning)
|
||||||
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldTick)
|
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldTick)
|
||||||
|
|
||||||
|
@ -861,6 +884,54 @@ void DStaticEventHandler::WorldLineActivated(line_t* line, AActor* actor, int ac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DStaticEventHandler::WorldSectorDamaged(sector_t* sector, AActor* source, int damage, FName damagetype, int part, DVector3 position, bool isradius)
|
||||||
|
{
|
||||||
|
IFVIRTUAL(DStaticEventHandler, WorldSectorDamaged)
|
||||||
|
{
|
||||||
|
// don't create excessive DObjects if not going to be processed anyway
|
||||||
|
if (func == DStaticEventHandler_WorldSectorDamaged_VMPtr)
|
||||||
|
return damage;
|
||||||
|
FWorldEvent e = E_SetupWorldEvent();
|
||||||
|
e.DamageSource = source;
|
||||||
|
e.DamageSector = sector;
|
||||||
|
e.NewDamage = e.Damage = damage;
|
||||||
|
e.DamageType = damagetype;
|
||||||
|
e.DamageSectorPart = part;
|
||||||
|
e.DamagePosition = position;
|
||||||
|
e.DamageIsRadius = isradius;
|
||||||
|
|
||||||
|
VMValue params[2] = { (DStaticEventHandler*)this, &e };
|
||||||
|
VMCall(func, params, 2, nullptr, 0);
|
||||||
|
return e.NewDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DStaticEventHandler::WorldLineDamaged(line_t* line, AActor* source, int damage, FName damagetype, int side, DVector3 position, bool isradius)
|
||||||
|
{
|
||||||
|
IFVIRTUAL(DStaticEventHandler, WorldLineDamaged)
|
||||||
|
{
|
||||||
|
// don't create excessive DObjects if not going to be processed anyway
|
||||||
|
if (func == DStaticEventHandler_WorldLineDamaged_VMPtr)
|
||||||
|
return damage;
|
||||||
|
FWorldEvent e = E_SetupWorldEvent();
|
||||||
|
e.DamageSource = source;
|
||||||
|
e.DamageLine = line;
|
||||||
|
e.NewDamage = e.Damage = damage;
|
||||||
|
e.DamageType = damagetype;
|
||||||
|
e.DamageLineSide = side;
|
||||||
|
e.DamagePosition = position;
|
||||||
|
e.DamageIsRadius = isradius;
|
||||||
|
|
||||||
|
VMValue params[2] = { (DStaticEventHandler*)this, &e };
|
||||||
|
VMCall(func, params, 2, nullptr, 0);
|
||||||
|
return e.NewDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
void DStaticEventHandler::WorldLightning()
|
void DStaticEventHandler::WorldLightning()
|
||||||
{
|
{
|
||||||
IFVIRTUAL(DStaticEventHandler, WorldLightning)
|
IFVIRTUAL(DStaticEventHandler, WorldLightning)
|
||||||
|
|
22
src/events.h
22
src/events.h
|
@ -50,6 +50,10 @@ void E_WorldThingDestroyed(AActor* actor);
|
||||||
void E_WorldLinePreActivated(line_t* line, AActor* actor, int activationType, bool* shouldactivate);
|
void E_WorldLinePreActivated(line_t* line, AActor* actor, int activationType, bool* shouldactivate);
|
||||||
// called in P_ActivateLine after successful special execution.
|
// called in P_ActivateLine after successful special execution.
|
||||||
void E_WorldLineActivated(line_t* line, AActor* actor, int activationType);
|
void E_WorldLineActivated(line_t* line, AActor* actor, int activationType);
|
||||||
|
// called in P_DamageSector and P_DamageLinedef before receiving damage to the sector. returns actual damage
|
||||||
|
int E_WorldSectorDamaged(sector_t* sector, AActor* source, int damage, FName damagetype, int part, DVector3 position, bool isradius);
|
||||||
|
// called in P_DamageLinedef before receiving damage to the linedef. returns actual damage
|
||||||
|
int E_WorldLineDamaged(line_t* line, AActor* source, int damage, FName damagetype, int side, DVector3 position, bool isradius);
|
||||||
// same as ACS SCRIPT_Lightning
|
// same as ACS SCRIPT_Lightning
|
||||||
void E_WorldLightning();
|
void E_WorldLightning();
|
||||||
// this executes on every tick, before everything, only when in valid level and not paused
|
// this executes on every tick, before everything, only when in valid level and not paused
|
||||||
|
@ -157,6 +161,8 @@ public:
|
||||||
void WorldThingDestroyed(AActor* actor);
|
void WorldThingDestroyed(AActor* actor);
|
||||||
void WorldLinePreActivated(line_t* line, AActor* actor, int activationType, bool* shouldactivate);
|
void WorldLinePreActivated(line_t* line, AActor* actor, int activationType, bool* shouldactivate);
|
||||||
void WorldLineActivated(line_t* line, AActor* actor, int activationType);
|
void WorldLineActivated(line_t* line, AActor* actor, int activationType);
|
||||||
|
int WorldSectorDamaged(sector_t* sector, AActor* source, int damage, FName damagetype, int part, DVector3 position, bool isradius);
|
||||||
|
int WorldLineDamaged(line_t* line, AActor* source, int damage, FName damagetype, int side, DVector3 position, bool isradius);
|
||||||
void WorldLightning();
|
void WorldLightning();
|
||||||
void WorldTick();
|
void WorldTick();
|
||||||
|
|
||||||
|
@ -215,14 +221,22 @@ struct FWorldEvent
|
||||||
AActor* Thing = nullptr; // for thingdied
|
AActor* Thing = nullptr; // for thingdied
|
||||||
AActor* Inflictor = nullptr; // can be null - for damagemobj
|
AActor* Inflictor = nullptr; // can be null - for damagemobj
|
||||||
AActor* DamageSource = nullptr; // can be null
|
AActor* DamageSource = nullptr; // can be null
|
||||||
int Damage = 0;
|
int Damage = 0; // thingdamaged, sector/line damaged
|
||||||
FName DamageType = NAME_None;
|
FName DamageType = NAME_None; // thingdamaged, sector/line damaged
|
||||||
int DamageFlags = 0;
|
int DamageFlags = 0; // thingdamaged
|
||||||
DAngle DamageAngle;
|
DAngle DamageAngle; // thingdamaged
|
||||||
// for line(pre)activated
|
// for line(pre)activated
|
||||||
line_t* ActivatedLine = nullptr;
|
line_t* ActivatedLine = nullptr;
|
||||||
int ActivationType = 0;
|
int ActivationType = 0;
|
||||||
bool ShouldActivate = true;
|
bool ShouldActivate = true;
|
||||||
|
// for line/sector damaged
|
||||||
|
int DamageSectorPart = 0;
|
||||||
|
line_t* DamageLine = nullptr;
|
||||||
|
sector_t* DamageSector = nullptr;
|
||||||
|
int DamageLineSide = -1;
|
||||||
|
DVector3 DamagePosition;
|
||||||
|
bool DamageIsRadius; // radius damage yes/no
|
||||||
|
int NewDamage = 0; // sector/line damaged. allows modifying damage
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FPlayerEvent
|
struct FPlayerEvent
|
||||||
|
|
|
@ -10,15 +10,16 @@
|
||||||
#include "p_maputl.h"
|
#include "p_maputl.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
|
#include "vm.h"
|
||||||
|
#include "events.h"
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// [ZZ] Geometry damage logic callbacks
|
// [ZZ] Geometry damage logic callbacks
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
void P_SetHealthGroupHealth(int group, int health)
|
void P_SetHealthGroupHealth(FHealthGroup* grp, int health)
|
||||||
{
|
{
|
||||||
FHealthGroup* grp = P_GetHealthGroup(group);
|
|
||||||
if (!grp) return;
|
if (!grp) return;
|
||||||
|
|
||||||
grp->health = health;
|
grp->health = health;
|
||||||
|
@ -33,16 +34,21 @@ void P_SetHealthGroupHealth(int group, int health)
|
||||||
for (unsigned i = 0; i < grp->sectors.Size(); i++)
|
for (unsigned i = 0; i < grp->sectors.Size(); i++)
|
||||||
{
|
{
|
||||||
sector_t* lsector = grp->sectors[i];
|
sector_t* lsector = grp->sectors[i];
|
||||||
if (lsector->healthceilinggroup == group)
|
if (lsector->healthceilinggroup == grp->id)
|
||||||
lsector->healthceiling = health;
|
lsector->healthceiling = health;
|
||||||
if (lsector->healthfloorgroup == group)
|
if (lsector->healthfloorgroup == grp->id)
|
||||||
lsector->healthfloor = health;
|
lsector->healthfloor = health;
|
||||||
if (lsector->health3dgroup == group)
|
if (lsector->health3dgroup == grp->id)
|
||||||
lsector->health3d = health;
|
lsector->health3d = health;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_DamageHealthGroup(FHealthGroup* grp, void* object, AActor* source, int damage, FName damagetype, int side, int part, DVector3 position)
|
void P_SetHealthGroupHealth(int id, int health)
|
||||||
|
{
|
||||||
|
P_SetHealthGroupHealth(P_GetHealthGroup(id), health);
|
||||||
|
}
|
||||||
|
|
||||||
|
void P_DamageHealthGroup(FHealthGroup* grp, void* object, AActor* source, int damage, FName damagetype, int side, int part, DVector3 position, bool isradius)
|
||||||
{
|
{
|
||||||
if (!grp) return;
|
if (!grp) return;
|
||||||
int group = grp->id;
|
int group = grp->id;
|
||||||
|
@ -54,7 +60,7 @@ void P_DamageHealthGroup(FHealthGroup* grp, void* object, AActor* source, int da
|
||||||
if (lline == object)
|
if (lline == object)
|
||||||
continue;
|
continue;
|
||||||
lline->health = grp->health + damage;
|
lline->health = grp->health + damage;
|
||||||
P_DamageLinedef(lline, source, damage, damagetype, side, position, false);
|
P_DamageLinedef(lline, source, damage, damagetype, side, position, isradius, false);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
for (unsigned i = 0; i < grp->sectors.Size(); i++)
|
for (unsigned i = 0; i < grp->sectors.Size(); i++)
|
||||||
|
@ -64,26 +70,33 @@ void P_DamageHealthGroup(FHealthGroup* grp, void* object, AActor* source, int da
|
||||||
if (lsector->healthceilinggroup == group && (lsector != object || part != SECPART_Ceiling))
|
if (lsector->healthceilinggroup == group && (lsector != object || part != SECPART_Ceiling))
|
||||||
{
|
{
|
||||||
lsector->healthceiling = grp->health + damage;
|
lsector->healthceiling = grp->health + damage;
|
||||||
P_DamageSector(lsector, source, damage, damagetype, SECPART_Ceiling, position, false);
|
P_DamageSector(lsector, source, damage, damagetype, SECPART_Ceiling, position, isradius, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lsector->healthfloorgroup == group && (lsector != object || part != SECPART_Floor))
|
if (lsector->healthfloorgroup == group && (lsector != object || part != SECPART_Floor))
|
||||||
{
|
{
|
||||||
lsector->healthfloor = grp->health + damage;
|
lsector->healthfloor = grp->health + damage;
|
||||||
P_DamageSector(lsector, source, damage, damagetype, SECPART_Floor, position, false);
|
P_DamageSector(lsector, source, damage, damagetype, SECPART_Floor, position, isradius, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lsector->health3dgroup == group && (lsector != object || part != SECPART_3D))
|
if (lsector->health3dgroup == group && (lsector != object || part != SECPART_3D))
|
||||||
{
|
{
|
||||||
lsector->health3d = grp->health + damage;
|
lsector->health3d = grp->health + damage;
|
||||||
P_DamageSector(lsector, source, damage, damagetype, SECPART_3D, position, false);
|
P_DamageSector(lsector, source, damage, damagetype, SECPART_3D, position, isradius, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_DamageLinedef(line_t* line, AActor* source, int damage, FName damagetype, int side, DVector3 position, bool dogroups)
|
void P_DamageLinedef(line_t* line, AActor* source, int damage, FName damagetype, int side, DVector3 position, bool isradius, bool dogroups)
|
||||||
{
|
{
|
||||||
if (damage < 0) damage = 0;
|
if (damage < 0) damage = 0;
|
||||||
|
|
||||||
|
if (dogroups)
|
||||||
|
{
|
||||||
|
damage = E_WorldLineDamaged(line, source, damage, damagetype, side, position, isradius);
|
||||||
|
if (damage < 0) damage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!damage) return;
|
if (!damage) return;
|
||||||
|
|
||||||
line->health -= damage;
|
line->health -= damage;
|
||||||
|
@ -103,15 +116,22 @@ void P_DamageLinedef(line_t* line, AActor* source, int damage, FName damagetype,
|
||||||
FHealthGroup* grp = P_GetHealthGroup(line->healthgroup);
|
FHealthGroup* grp = P_GetHealthGroup(line->healthgroup);
|
||||||
if (grp)
|
if (grp)
|
||||||
grp->health = line->health;
|
grp->health = line->health;
|
||||||
P_DamageHealthGroup(grp, line, source, damage, damagetype, side, -1, position);
|
P_DamageHealthGroup(grp, line, source, damage, damagetype, side, -1, position, isradius);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Printf("P_DamageLinedef: %d damage (type=%s, source=%p), new health = %d\n", damage, damagetype.GetChars(), source, line->health);
|
//Printf("P_DamageLinedef: %d damage (type=%s, source=%p), new health = %d\n", damage, damagetype.GetChars(), source, line->health);
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_DamageSector(sector_t* sector, AActor* source, int damage, FName damagetype, int part, DVector3 position, bool dogroups)
|
void P_DamageSector(sector_t* sector, AActor* source, int damage, FName damagetype, int part, DVector3 position, bool isradius, bool dogroups)
|
||||||
{
|
{
|
||||||
if (damage < 0) damage = 0;
|
if (damage < 0) damage = 0;
|
||||||
|
|
||||||
|
if (dogroups)
|
||||||
|
{
|
||||||
|
damage = E_WorldSectorDamaged(sector, source, damage, damagetype, part, position, isradius);
|
||||||
|
if (damage < 0) damage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!damage) return;
|
if (!damage) return;
|
||||||
|
|
||||||
int* sectorhealth;
|
int* sectorhealth;
|
||||||
|
@ -160,7 +180,7 @@ void P_DamageSector(sector_t* sector, AActor* source, int damage, FName damagety
|
||||||
FHealthGroup* grp = P_GetHealthGroup(group);
|
FHealthGroup* grp = P_GetHealthGroup(group);
|
||||||
if (grp)
|
if (grp)
|
||||||
grp->health = newhealth;
|
grp->health = newhealth;
|
||||||
P_DamageHealthGroup(grp, sector, source, damage, damagetype, 0, part, position);
|
P_DamageHealthGroup(grp, sector, source, damage, damagetype, 0, part, position, isradius);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Printf("P_DamageSector: %d damage (type=%s, position=%s, source=%p), new health = %d\n", damage, damagetype.GetChars(), (part == SECPART_Ceiling) ? "ceiling" : "floor", source, newhealth);
|
//Printf("P_DamageSector: %d damage (type=%s, position=%s, source=%p), new health = %d\n", damage, damagetype.GetChars(), (part == SECPART_Ceiling) ? "ceiling" : "floor", source, newhealth);
|
||||||
|
@ -264,7 +284,7 @@ void P_GeometryLineAttack(FTraceResults& trace, AActor* thing, int damage, FName
|
||||||
if (trace.HitType == TRACE_HitWall && trace.Tier == TIER_FFloor)
|
if (trace.HitType == TRACE_HitWall && trace.Tier == TIER_FFloor)
|
||||||
{
|
{
|
||||||
if (trace.ffloor && trace.ffloor->model && trace.ffloor->model->health3d)
|
if (trace.ffloor && trace.ffloor->model && trace.ffloor->model->health3d)
|
||||||
P_DamageSector(trace.ffloor->model, thing, damage, damageType, SECPART_3D, trace.HitPos);
|
P_DamageSector(trace.ffloor->model, thing, damage, damageType, SECPART_3D, trace.HitPos, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trace.HitType == TRACE_HitWall && P_CheckLinedefVulnerable(trace.Line, trace.Side))
|
if (trace.HitType == TRACE_HitWall && P_CheckLinedefVulnerable(trace.Line, trace.Side))
|
||||||
|
@ -279,13 +299,13 @@ void P_GeometryLineAttack(FTraceResults& trace, AActor* thing, int damage, FName
|
||||||
sectorhealth = backsector->healthceiling;
|
sectorhealth = backsector->healthceiling;
|
||||||
if (sectorhealth > 0)
|
if (sectorhealth > 0)
|
||||||
{
|
{
|
||||||
P_DamageSector(backsector, thing, damage, damageType, (trace.Tier == TIER_Upper) ? SECPART_Ceiling : SECPART_Floor, trace.HitPos);
|
P_DamageSector(backsector, thing, damage, damageType, (trace.Tier == TIER_Upper) ? SECPART_Ceiling : SECPART_Floor, trace.HitPos, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// always process linedef health if any
|
// always process linedef health if any
|
||||||
if (trace.Line->health > 0)
|
if (trace.Line->health > 0)
|
||||||
{
|
{
|
||||||
P_DamageLinedef(trace.Line, thing, damage, damageType, trace.Side, trace.HitPos);
|
P_DamageLinedef(trace.Line, thing, damage, damageType, trace.Side, trace.HitPos, false, true);
|
||||||
}
|
}
|
||||||
// fake floors are not handled
|
// fake floors are not handled
|
||||||
}
|
}
|
||||||
|
@ -304,13 +324,13 @@ void P_GeometryLineAttack(FTraceResults& trace, AActor* thing, int damage, FName
|
||||||
if (trace.HitType == TRACE_HitFloor && fabs(f->top.plane->ZatPoint(trace.HitPos.XY())-trace.HitPos.Z) <= EQUAL_EPSILON)
|
if (trace.HitType == TRACE_HitFloor && fabs(f->top.plane->ZatPoint(trace.HitPos.XY())-trace.HitPos.Z) <= EQUAL_EPSILON)
|
||||||
{
|
{
|
||||||
if (f->model->health3d)
|
if (f->model->health3d)
|
||||||
P_DamageSector(f->model, thing, damage, damageType, SECPART_3D, trace.HitPos);
|
P_DamageSector(f->model, thing, damage, damageType, SECPART_3D, trace.HitPos, false, true);
|
||||||
hit3dfloors = true;
|
hit3dfloors = true;
|
||||||
}
|
}
|
||||||
else if (trace.HitType == TRACE_HitCeiling && fabs(f->bottom.plane->ZatPoint(trace.HitPos.XY())-trace.HitPos.Z) <= EQUAL_EPSILON)
|
else if (trace.HitType == TRACE_HitCeiling && fabs(f->bottom.plane->ZatPoint(trace.HitPos.XY())-trace.HitPos.Z) <= EQUAL_EPSILON)
|
||||||
{
|
{
|
||||||
if (f->model->health3d)
|
if (f->model->health3d)
|
||||||
P_DamageSector(f->model, thing, damage, damageType, SECPART_3D, trace.HitPos);
|
P_DamageSector(f->model, thing, damage, damageType, SECPART_3D, trace.HitPos, false, true);
|
||||||
hit3dfloors = true;
|
hit3dfloors = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,7 +345,7 @@ void P_GeometryLineAttack(FTraceResults& trace, AActor* thing, int damage, FName
|
||||||
sectorhealth = trace.Sector->healthceiling;
|
sectorhealth = trace.Sector->healthceiling;
|
||||||
if (sectorhealth > 0)
|
if (sectorhealth > 0)
|
||||||
{
|
{
|
||||||
P_DamageSector(trace.Sector, thing, damage, damageType, (trace.HitType == TRACE_HitCeiling) ? SECPART_Ceiling : SECPART_Floor, trace.HitPos);
|
P_DamageSector(trace.Sector, thing, damage, damageType, (trace.HitType == TRACE_HitCeiling) ? SECPART_Ceiling : SECPART_Floor, trace.HitPos, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -539,7 +559,7 @@ void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage
|
||||||
if (bombsource == bombspot)
|
if (bombsource == bombspot)
|
||||||
damage = (int)(damage * splashfactor);
|
damage = (int)(damage * splashfactor);
|
||||||
}
|
}
|
||||||
P_DamageLinedef(ln, bombsource, damage, damagetype, sd, to3d_fullheight);
|
P_DamageLinedef(ln, bombsource, damage, damagetype, sd, to3d_fullheight, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -620,24 +640,24 @@ void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage
|
||||||
if (grp & 0x80000000) // sector ceiling
|
if (grp & 0x80000000) // sector ceiling
|
||||||
{
|
{
|
||||||
assert(damageGroupPair->Value.sector != nullptr);
|
assert(damageGroupPair->Value.sector != nullptr);
|
||||||
P_DamageSector(damageGroupPair->Value.sector, bombsource, damage, damagetype, SECPART_Ceiling, pos);
|
P_DamageSector(damageGroupPair->Value.sector, bombsource, damage, damagetype, SECPART_Ceiling, pos, true, true);
|
||||||
}
|
}
|
||||||
else if (grp & 0x40000000) // sector floor
|
else if (grp & 0x40000000) // sector floor
|
||||||
{
|
{
|
||||||
assert(damageGroupPair->Value.sector != nullptr);
|
assert(damageGroupPair->Value.sector != nullptr);
|
||||||
P_DamageSector(damageGroupPair->Value.sector, bombsource, damage, damagetype, SECPART_Floor, pos);
|
P_DamageSector(damageGroupPair->Value.sector, bombsource, damage, damagetype, SECPART_Floor, pos, true, true);
|
||||||
}
|
}
|
||||||
else if (grp & 0x20000000) // sector 3d
|
else if (grp & 0x20000000) // sector 3d
|
||||||
{
|
{
|
||||||
assert(damageGroupPair->Value.sector != nullptr);
|
assert(damageGroupPair->Value.sector != nullptr);
|
||||||
P_DamageSector(damageGroupPair->Value.sector, bombsource, damage, damagetype, SECPART_3D, pos);
|
P_DamageSector(damageGroupPair->Value.sector, bombsource, damage, damagetype, SECPART_3D, pos, true, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert((damageGroupPair->Value.sector != nullptr) != (damageGroupPair->Value.line != nullptr));
|
assert((damageGroupPair->Value.sector != nullptr) != (damageGroupPair->Value.line != nullptr));
|
||||||
if (damageGroupPair->Value.line != nullptr)
|
if (damageGroupPair->Value.line != nullptr)
|
||||||
P_DamageLinedef(damageGroupPair->Value.line, bombsource, damage, damagetype, P_PointOnLineSide(pos.XY(), damageGroupPair->Value.line), pos);
|
P_DamageLinedef(damageGroupPair->Value.line, bombsource, damage, damagetype, P_PointOnLineSide(pos.XY(), damageGroupPair->Value.line), pos, true, true);
|
||||||
else P_DamageSector(damageGroupPair->Value.sector, bombsource, damage, damagetype, damageGroupPair->Value.secpart, pos);
|
else P_DamageSector(damageGroupPair->Value.sector, bombsource, damage, damagetype, damageGroupPair->Value.secpart, pos, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -657,7 +677,7 @@ bool P_ProjectileHitLinedef(AActor* mo, line_t* line)
|
||||||
{
|
{
|
||||||
if (mo->Blocking3DFloor->health3d > 0)
|
if (mo->Blocking3DFloor->health3d > 0)
|
||||||
{
|
{
|
||||||
P_DamageSector(mo->Blocking3DFloor, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_3D, mo->Pos());
|
P_DamageSector(mo->Blocking3DFloor, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_3D, mo->Pos(), false, true);
|
||||||
washit = true;
|
washit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -682,19 +702,19 @@ bool P_ProjectileHitLinedef(AActor* mo, line_t* line)
|
||||||
double ztop = mo->Pos().Z + mo->Height;
|
double ztop = mo->Pos().Z + mo->Height;
|
||||||
if (zbottom < (otherfloorz + EQUAL_EPSILON) && othersector->healthfloor > 0 && P_CheckLinedefVulnerable(line, wside, SECPART_Floor))
|
if (zbottom < (otherfloorz + EQUAL_EPSILON) && othersector->healthfloor > 0 && P_CheckLinedefVulnerable(line, wside, SECPART_Floor))
|
||||||
{
|
{
|
||||||
P_DamageSector(othersector, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_Floor, mo->Pos());
|
P_DamageSector(othersector, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_Floor, mo->Pos(), false, true);
|
||||||
washit = true;
|
washit = true;
|
||||||
}
|
}
|
||||||
if (ztop > (otherceilingz - EQUAL_EPSILON) && othersector->healthceiling > 0 && P_CheckLinedefVulnerable(line, wside, SECPART_Ceiling))
|
if (ztop > (otherceilingz - EQUAL_EPSILON) && othersector->healthceiling > 0 && P_CheckLinedefVulnerable(line, wside, SECPART_Ceiling))
|
||||||
{
|
{
|
||||||
P_DamageSector(othersector, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_Ceiling, mo->Pos());
|
P_DamageSector(othersector, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_Ceiling, mo->Pos(), false, true);
|
||||||
washit = true;
|
washit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line->health > 0 && P_CheckLinedefVulnerable(line, wside))
|
if (line->health > 0 && P_CheckLinedefVulnerable(line, wside))
|
||||||
{
|
{
|
||||||
P_DamageLinedef(line, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, wside, mo->Pos());
|
P_DamageLinedef(line, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, wside, mo->Pos(), false, true);
|
||||||
washit = true;
|
washit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,7 +737,7 @@ bool P_ProjectileHitPlane(AActor* mo, int part)
|
||||||
{
|
{
|
||||||
if (mo->Blocking3DFloor->health3d > 0)
|
if (mo->Blocking3DFloor->health3d > 0)
|
||||||
{
|
{
|
||||||
P_DamageSector(mo->Blocking3DFloor, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_3D, mo->Pos());
|
P_DamageSector(mo->Blocking3DFloor, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_3D, mo->Pos(), false, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,12 +746,12 @@ bool P_ProjectileHitPlane(AActor* mo, int part)
|
||||||
|
|
||||||
if (part == SECPART_Floor && mo->Sector->healthfloor > 0 && P_CheckSectorVulnerable(mo->Sector, SECPART_Floor))
|
if (part == SECPART_Floor && mo->Sector->healthfloor > 0 && P_CheckSectorVulnerable(mo->Sector, SECPART_Floor))
|
||||||
{
|
{
|
||||||
P_DamageSector(mo->Sector, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_Floor, mo->Pos());
|
P_DamageSector(mo->Sector, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_Floor, mo->Pos(), false, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (part == SECPART_Ceiling && mo->Sector->healthceiling > 0 && P_CheckSectorVulnerable(mo->Sector, SECPART_Ceiling))
|
else if (part == SECPART_Ceiling && mo->Sector->healthceiling > 0 && P_CheckSectorVulnerable(mo->Sector, SECPART_Ceiling))
|
||||||
{
|
{
|
||||||
P_DamageSector(mo->Sector, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_Ceiling, mo->Pos());
|
P_DamageSector(mo->Sector, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_Ceiling, mo->Pos(), false, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,3 +841,205 @@ void P_SerializeHealthGroups(FSerializer& arc)
|
||||||
arc.EndArray();
|
arc.EndArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===================== zscript interface =====================
|
||||||
|
//
|
||||||
|
// =============================================================
|
||||||
|
|
||||||
|
DEFINE_FIELD_X(HealthGroup, FHealthGroup, id)
|
||||||
|
DEFINE_FIELD_X(HealthGroup, FHealthGroup, health)
|
||||||
|
DEFINE_FIELD_X(HealthGroup, FHealthGroup, sectors)
|
||||||
|
DEFINE_FIELD_X(HealthGroup, FHealthGroup, lines)
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FHealthGroup, Find)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_INT(id);
|
||||||
|
FHealthGroup* grp = P_GetHealthGroup(id);
|
||||||
|
ACTION_RETURN_POINTER(grp);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FHealthGroup, SetHealth)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FHealthGroup);
|
||||||
|
PARAM_INT(health);
|
||||||
|
P_SetHealthGroupHealth(self, health);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// genuine hack. this essentially causes the engine to register a struct called Destructible, and enables use of DEFINE_ACTION_FUNCTION
|
||||||
|
struct FDestructible { void* none; };
|
||||||
|
DEFINE_FIELD_X(Destructible, FDestructible, none);
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FDestructible, DamageSector)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_POINTER(sec, sector_t);
|
||||||
|
PARAM_OBJECT(source, AActor);
|
||||||
|
PARAM_INT(damage);
|
||||||
|
PARAM_NAME(damagetype);
|
||||||
|
PARAM_INT(part);
|
||||||
|
PARAM_FLOAT(position_x);
|
||||||
|
PARAM_FLOAT(position_y);
|
||||||
|
PARAM_FLOAT(position_z);
|
||||||
|
PARAM_BOOL(isradius);
|
||||||
|
P_DamageSector(sec, source, damage, damagetype, part, DVector3(position_x, position_y, position_z), isradius, true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FDestructible, DamageLinedef)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_POINTER(def, line_t);
|
||||||
|
PARAM_OBJECT(source, AActor);
|
||||||
|
PARAM_INT(damage);
|
||||||
|
PARAM_NAME(damagetype);
|
||||||
|
PARAM_INT(side);
|
||||||
|
PARAM_FLOAT(position_x);
|
||||||
|
PARAM_FLOAT(position_y);
|
||||||
|
PARAM_FLOAT(position_z);
|
||||||
|
PARAM_BOOL(isradius);
|
||||||
|
P_DamageLinedef(def, source, damage, damagetype, side, DVector3(position_x, position_y, position_z), isradius, true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FDestructible, GeometryLineAttack)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_POINTER(trace, FTraceResults);
|
||||||
|
PARAM_OBJECT(thing, AActor);
|
||||||
|
PARAM_INT(damage);
|
||||||
|
PARAM_NAME(damagetype);
|
||||||
|
P_GeometryLineAttack(*trace, thing, damage, damagetype);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FDestructible, GeometryRadiusAttack)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_OBJECT(bombspot, AActor);
|
||||||
|
PARAM_OBJECT(bombsource, AActor);
|
||||||
|
PARAM_INT(bombdamage);
|
||||||
|
PARAM_INT(bombdistance);
|
||||||
|
PARAM_NAME(damagetype);
|
||||||
|
PARAM_INT(fulldamagedistance);
|
||||||
|
P_GeometryRadiusAttack(bombspot, bombsource, bombdamage, bombdistance, damagetype, fulldamagedistance);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FDestructible, ProjectileHitLinedef)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_OBJECT(projectile, AActor);
|
||||||
|
PARAM_POINTER(def, line_t);
|
||||||
|
ACTION_RETURN_BOOL(P_ProjectileHitLinedef(projectile, def));
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FDestructible, ProjectileHitPlane)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_OBJECT(projectile, AActor);
|
||||||
|
PARAM_INT(part);
|
||||||
|
ACTION_RETURN_BOOL(P_ProjectileHitPlane(projectile, part));
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FDestructible, CheckLinedefVulnerable)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_POINTER(def, line_t);
|
||||||
|
PARAM_INT(side);
|
||||||
|
PARAM_INT(part);
|
||||||
|
ACTION_RETURN_BOOL(P_CheckLinedefVulnerable(def, side, part));
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FDestructible, CheckSectorVulnerable)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_POINTER(sec, sector_t);
|
||||||
|
PARAM_INT(part);
|
||||||
|
ACTION_RETURN_BOOL(P_CheckSectorVulnerable(sec, part));
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_Line, GetHealth)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(line_t);
|
||||||
|
if (self->healthgroup)
|
||||||
|
{
|
||||||
|
FHealthGroup* grp = P_GetHealthGroup(self->healthgroup);
|
||||||
|
if (grp) ACTION_RETURN_INT(grp->health);
|
||||||
|
}
|
||||||
|
|
||||||
|
ACTION_RETURN_INT(self->health);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_Line, SetHealth)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(line_t);
|
||||||
|
PARAM_INT(newhealth);
|
||||||
|
|
||||||
|
if (newhealth < 0)
|
||||||
|
newhealth = 0;
|
||||||
|
|
||||||
|
self->health = newhealth;
|
||||||
|
if (self->healthgroup)
|
||||||
|
{
|
||||||
|
FHealthGroup* grp = P_GetHealthGroup(self->healthgroup);
|
||||||
|
if (grp) P_SetHealthGroupHealth(grp, newhealth);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_Sector, GetHealth)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(sector_t);
|
||||||
|
PARAM_INT(part);
|
||||||
|
|
||||||
|
FHealthGroup* grp;
|
||||||
|
switch (part)
|
||||||
|
{
|
||||||
|
case SECPART_Floor:
|
||||||
|
ACTION_RETURN_INT((self->healthfloorgroup && (grp = P_GetHealthGroup(self->healthfloorgroup))) ? grp->health : self->healthfloor);
|
||||||
|
case SECPART_Ceiling:
|
||||||
|
ACTION_RETURN_INT((self->healthceilinggroup && (grp = P_GetHealthGroup(self->healthceilinggroup))) ? grp->health : self->healthceiling);
|
||||||
|
case SECPART_3D:
|
||||||
|
ACTION_RETURN_INT((self->health3dgroup && (grp = P_GetHealthGroup(self->health3dgroup))) ? grp->health : self->health3d);
|
||||||
|
default:
|
||||||
|
ACTION_RETURN_INT(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_Sector, SetHealth)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(sector_t);
|
||||||
|
PARAM_INT(part);
|
||||||
|
PARAM_INT(newhealth);
|
||||||
|
|
||||||
|
if (newhealth < 0)
|
||||||
|
newhealth = 0;
|
||||||
|
|
||||||
|
int group;
|
||||||
|
int* health;
|
||||||
|
switch (part)
|
||||||
|
{
|
||||||
|
case SECPART_Floor:
|
||||||
|
group = self->healthfloorgroup;
|
||||||
|
health = &self->healthfloor;
|
||||||
|
break;
|
||||||
|
case SECPART_Ceiling:
|
||||||
|
group = self->healthceilinggroup;
|
||||||
|
health = &self->healthceiling;
|
||||||
|
break;
|
||||||
|
case SECPART_3D:
|
||||||
|
group = self->health3dgroup;
|
||||||
|
health = &self->health3d;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FHealthGroup* grp = group ? P_GetHealthGroup(group) : nullptr;
|
||||||
|
*health = newhealth;
|
||||||
|
if (grp) P_SetHealthGroupHealth(grp, newhealth);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -23,13 +23,14 @@ enum
|
||||||
|
|
||||||
void P_InitHealthGroups();
|
void P_InitHealthGroups();
|
||||||
|
|
||||||
|
void P_SetHealthGroupHealth(FHealthGroup* group, int health);
|
||||||
void P_SetHealthGroupHealth(int group, int health);
|
void P_SetHealthGroupHealth(int group, int health);
|
||||||
|
|
||||||
FHealthGroup* P_GetHealthGroup(int id);
|
FHealthGroup* P_GetHealthGroup(int id);
|
||||||
FHealthGroup* P_GetHealthGroupOrNew(int id, int startinghealth);
|
FHealthGroup* P_GetHealthGroupOrNew(int id, int startinghealth);
|
||||||
|
|
||||||
void P_DamageSector(sector_t* sector, AActor* source, int damage, FName damagetype, int part, DVector3 position, bool dogroups = true);
|
void P_DamageSector(sector_t* sector, AActor* source, int damage, FName damagetype, int part, DVector3 position, bool isradius, bool dogroups);
|
||||||
void P_DamageLinedef(line_t* line, AActor* source, int damage, FName damagetype, int side, DVector3 position, bool dogroups = true);
|
void P_DamageLinedef(line_t* line, AActor* source, int damage, FName damagetype, int side, DVector3 position, bool isradius, bool dogroups);
|
||||||
|
|
||||||
void P_GeometryLineAttack(FTraceResults& trace, AActor* thing, int damage, FName damageType);
|
void P_GeometryLineAttack(FTraceResults& trace, AActor* thing, int damage, FName damageType);
|
||||||
void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage, int bombdistance, FName damagetype, int fulldamagedistance);
|
void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage, int bombdistance, FName damagetype, int fulldamagedistance);
|
||||||
|
|
|
@ -7,6 +7,7 @@ version "3.7"
|
||||||
#include "zscript/actor.txt"
|
#include "zscript/actor.txt"
|
||||||
#include "zscript/actor_checks.txt"
|
#include "zscript/actor_checks.txt"
|
||||||
#include "zscript/events.txt"
|
#include "zscript/events.txt"
|
||||||
|
#include "zscript/destructible.txt"
|
||||||
#include "zscript/level_compatibility.txt"
|
#include "zscript/level_compatibility.txt"
|
||||||
|
|
||||||
#include "zscript/menu/menuitembase.txt"
|
#include "zscript/menu/menuitembase.txt"
|
||||||
|
|
34
wadsrc/static/zscript/destructible.txt
Executable file
34
wadsrc/static/zscript/destructible.txt
Executable file
|
@ -0,0 +1,34 @@
|
||||||
|
struct HealthGroup native play
|
||||||
|
{
|
||||||
|
static clearscope native HealthGroup Find(int id);
|
||||||
|
|
||||||
|
readonly int id;
|
||||||
|
readonly int health;
|
||||||
|
readonly Array<Sector> sectors;
|
||||||
|
readonly Array<Line> lines;
|
||||||
|
|
||||||
|
native void SetHealth(int newhealth);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SectorPart
|
||||||
|
{
|
||||||
|
SECPART_None = -1,
|
||||||
|
SECPART_Floor = 0,
|
||||||
|
SECPART_Ceiling = 1,
|
||||||
|
SECPART_3D = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Destructible native play
|
||||||
|
{
|
||||||
|
|
||||||
|
static native void DamageSector(Sector sec, Actor source, int damage, Name damagetype, SectorPart part, vector3 position, bool isradius);
|
||||||
|
static native void DamageLinedef(Line def, Actor source, int damage, Name damagetype, int side, vector3 position, bool isradius);
|
||||||
|
|
||||||
|
static native void GeometryLineAttack(TraceResults trace, Actor thing, int damage, Name damagetype);
|
||||||
|
static native void GeometryRadiusAttack(Actor bombspot, Actor bombsource, int bombdamage, int bombdistance, Name damagetype, int fulldamagedistance);
|
||||||
|
static native bool ProjectileHitLinedef(Actor projectile, Line def);
|
||||||
|
static native bool ProjectileHitPlane(Actor projectile, SectorPart part);
|
||||||
|
|
||||||
|
static clearscope native bool CheckLinedefVulnerable(Line def, int side, SectorPart part);
|
||||||
|
static clearscope native bool CheckSectorVulnerable(Sector sec, SectorPart part);
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ struct WorldEvent native play version("2.4")
|
||||||
native readonly Actor Thing;
|
native readonly Actor Thing;
|
||||||
// for thingdied. can be null
|
// for thingdied. can be null
|
||||||
native readonly Actor Inflictor;
|
native readonly Actor Inflictor;
|
||||||
// for thingdamaged.
|
// for thingdamaged, line/sector damaged
|
||||||
native readonly int Damage;
|
native readonly int Damage;
|
||||||
native readonly Actor DamageSource;
|
native readonly Actor DamageSource;
|
||||||
native readonly Name DamageType;
|
native readonly Name DamageType;
|
||||||
|
@ -29,6 +29,14 @@ struct WorldEvent native play version("2.4")
|
||||||
native readonly Line ActivatedLine;
|
native readonly Line ActivatedLine;
|
||||||
native readonly int ActivationType;
|
native readonly int ActivationType;
|
||||||
native bool ShouldActivate;
|
native bool ShouldActivate;
|
||||||
|
// for line/sector damaged
|
||||||
|
native readonly SectorPart DamageSectorPart;
|
||||||
|
native readonly Line DamageLine;
|
||||||
|
native readonly Sector DamageSector;
|
||||||
|
native readonly int DamageLineSide;
|
||||||
|
native readonly vector3 DamagePosition;
|
||||||
|
native readonly bool DamageIsRadius;
|
||||||
|
native int NewDamage;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PlayerEvent native play version("2.4")
|
struct PlayerEvent native play version("2.4")
|
||||||
|
@ -313,6 +321,8 @@ class StaticEventHandler : Object native play version("2.4")
|
||||||
virtual native void WorldThingDestroyed(WorldEvent e);
|
virtual native void WorldThingDestroyed(WorldEvent e);
|
||||||
virtual native void WorldLinePreActivated(WorldEvent e);
|
virtual native void WorldLinePreActivated(WorldEvent e);
|
||||||
virtual native void WorldLineActivated(WorldEvent e);
|
virtual native void WorldLineActivated(WorldEvent e);
|
||||||
|
virtual native void WorldSectorDamaged(WorldEvent e);
|
||||||
|
virtual native void WorldLineDamaged(WorldEvent e);
|
||||||
virtual native void WorldLightning(WorldEvent e); // for the sake of completeness.
|
virtual native void WorldLightning(WorldEvent e); // for the sake of completeness.
|
||||||
virtual native void WorldTick();
|
virtual native void WorldTick();
|
||||||
|
|
||||||
|
|
|
@ -180,6 +180,9 @@ struct Line native play
|
||||||
{
|
{
|
||||||
return Level.GetUDMFString(LevelLocals.UDMF_Line, Index(), nm);
|
return Level.GetUDMFString(LevelLocals.UDMF_Line, Index(), nm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
native clearscope int GetHealth();
|
||||||
|
native void SetHealth(int newhealth);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SecPlane native play
|
struct SecPlane native play
|
||||||
|
@ -479,6 +482,8 @@ struct Sector native play
|
||||||
return Level.GetUDMFString(LevelLocals.UDMF_Sector, Index(), nm);
|
return Level.GetUDMFString(LevelLocals.UDMF_Sector, Index(), nm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
native clearscope int GetHealth(SectorPart part);
|
||||||
|
native void SetHealth(SectorPart part, int newhealth);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SectorTagIterator : Object native
|
class SectorTagIterator : Object native
|
||||||
|
|
|
@ -148,6 +148,7 @@ class FastProjectile : Actor
|
||||||
|
|
||||||
SetZ(floorz);
|
SetZ(floorz);
|
||||||
HitFloor ();
|
HitFloor ();
|
||||||
|
Destructible.ProjectileHitPlane(self, SECPART_Floor);
|
||||||
ExplodeMissile (NULL, NULL);
|
ExplodeMissile (NULL, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -161,6 +162,7 @@ class FastProjectile : Actor
|
||||||
}
|
}
|
||||||
|
|
||||||
SetZ(ceilingz - Height);
|
SetZ(ceilingz - Height);
|
||||||
|
Destructible.ProjectileHitPlane(self, SECPART_Ceiling);
|
||||||
ExplodeMissile (NULL, NULL);
|
ExplodeMissile (NULL, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue