mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
This commit is contained in:
commit
b3a69e1df8
20 changed files with 135 additions and 76 deletions
52
src/actor.h
52
src/actor.h
|
@ -807,11 +807,6 @@ public:
|
||||||
return (flags & MF_COUNTKILL) && !(flags & MF_FRIENDLY);
|
return (flags & MF_COUNTKILL) && !(flags & MF_FRIENDLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
PalEntry GetBloodColor() const
|
|
||||||
{
|
|
||||||
return GetClass()->BloodColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These also set CF_INTERPVIEW for players.
|
// These also set CF_INTERPVIEW for players.
|
||||||
void SetPitch(DAngle p, bool interpolate, bool forceclamp = false);
|
void SetPitch(DAngle p, bool interpolate, bool forceclamp = false);
|
||||||
void SetAngle(DAngle ang, bool interpolate);
|
void SetAngle(DAngle ang, bool interpolate);
|
||||||
|
@ -983,29 +978,42 @@ public:
|
||||||
// NOTE: The first member variable *must* be snext.
|
// NOTE: The first member variable *must* be snext.
|
||||||
AActor *snext, **sprev; // links in sector (if needed)
|
AActor *snext, **sprev; // links in sector (if needed)
|
||||||
DVector3 __Pos; // double underscores so that it won't get used by accident. Access to this should be exclusively through the designated access functions.
|
DVector3 __Pos; // double underscores so that it won't get used by accident. Access to this should be exclusively through the designated access functions.
|
||||||
DVector3 OldRenderPos;
|
|
||||||
|
|
||||||
DAngle SpriteAngle;
|
DAngle SpriteAngle;
|
||||||
DAngle SpriteRotation;
|
DAngle SpriteRotation;
|
||||||
DAngle VisibleStartAngle;
|
|
||||||
DAngle VisibleStartPitch;
|
|
||||||
DAngle VisibleEndAngle;
|
|
||||||
DAngle VisibleEndPitch;
|
|
||||||
DRotator Angles;
|
DRotator Angles;
|
||||||
DVector3 Vel;
|
DVector2 Scale; // Scaling values; 1 is normal size
|
||||||
double Speed;
|
double Alpha; // Since P_CheckSight makes an alpha check this can't be a float. It has to be a double.
|
||||||
double FloatSpeed;
|
|
||||||
|
|
||||||
int sprite; // used to find patch_t and flip value
|
int sprite; // used to find patch_t and flip value
|
||||||
uint8_t frame; // sprite frame to draw
|
uint8_t frame; // sprite frame to draw
|
||||||
uint8_t effects; // [RH] see p_effect.h
|
uint8_t effects; // [RH] see p_effect.h
|
||||||
uint8_t fountaincolor; // Split out of 'effect' to have easier access.
|
uint8_t fountaincolor; // Split out of 'effect' to have easier access.
|
||||||
DVector2 Scale; // Scaling values; 1 is normal size
|
|
||||||
FRenderStyle RenderStyle; // Style to draw this actor with
|
FRenderStyle RenderStyle; // Style to draw this actor with
|
||||||
ActorRenderFlags renderflags; // Different rendering flags
|
|
||||||
FTextureID picnum; // Draw this instead of sprite if valid
|
FTextureID picnum; // Draw this instead of sprite if valid
|
||||||
double Alpha; // Since P_CheckSight makes an alpha check this can't be a float. It has to be a double.
|
|
||||||
DWORD fillcolor; // Color to draw when STYLE_Shaded
|
DWORD fillcolor; // Color to draw when STYLE_Shaded
|
||||||
|
DWORD Translation;
|
||||||
|
|
||||||
|
ActorRenderFlags renderflags; // Different rendering flags
|
||||||
|
ActorFlags flags;
|
||||||
|
ActorFlags2 flags2; // Heretic flags
|
||||||
|
ActorFlags3 flags3; // [RH] Hexen/Heretic actor-dependant behavior made flaggable
|
||||||
|
ActorFlags4 flags4; // [RH] Even more flags!
|
||||||
|
ActorFlags5 flags5; // OMG! We need another one.
|
||||||
|
ActorFlags6 flags6; // Shit! Where did all the flags go?
|
||||||
|
ActorFlags7 flags7; // WHO WANTS TO BET ON 8!?
|
||||||
|
double Floorclip; // value to use for floor clipping
|
||||||
|
double radius, Height; // for movement checking
|
||||||
|
|
||||||
|
DAngle VisibleStartAngle;
|
||||||
|
DAngle VisibleStartPitch;
|
||||||
|
DAngle VisibleEndAngle;
|
||||||
|
DAngle VisibleEndPitch;
|
||||||
|
|
||||||
|
DVector3 OldRenderPos;
|
||||||
|
DVector3 Vel;
|
||||||
|
double Speed;
|
||||||
|
double FloatSpeed;
|
||||||
|
|
||||||
// interaction info
|
// interaction info
|
||||||
FBlockNode *BlockNode; // links in blocks (if needed)
|
FBlockNode *BlockNode; // links in blocks (if needed)
|
||||||
|
@ -1019,7 +1027,6 @@ public:
|
||||||
int floorterrain;
|
int floorterrain;
|
||||||
struct sector_t *ceilingsector;
|
struct sector_t *ceilingsector;
|
||||||
FTextureID ceilingpic; // contacted sec ceilingpic
|
FTextureID ceilingpic; // contacted sec ceilingpic
|
||||||
double radius, Height; // for movement checking
|
|
||||||
double renderradius;
|
double renderradius;
|
||||||
|
|
||||||
double projectilepassheight; // height for clipping projectile movement against this actor
|
double projectilepassheight; // height for clipping projectile movement against this actor
|
||||||
|
@ -1036,13 +1043,6 @@ public:
|
||||||
int DamageVal;
|
int DamageVal;
|
||||||
VMFunction *DamageFunc;
|
VMFunction *DamageFunc;
|
||||||
int projectileKickback;
|
int projectileKickback;
|
||||||
ActorFlags flags;
|
|
||||||
ActorFlags2 flags2; // Heretic flags
|
|
||||||
ActorFlags3 flags3; // [RH] Hexen/Heretic actor-dependant behavior made flaggable
|
|
||||||
ActorFlags4 flags4; // [RH] Even more flags!
|
|
||||||
ActorFlags5 flags5; // OMG! We need another one.
|
|
||||||
ActorFlags6 flags6; // Shit! Where did all the flags go?
|
|
||||||
ActorFlags7 flags7; // WHO WANTS TO BET ON 8!?
|
|
||||||
|
|
||||||
// [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it.
|
// [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it.
|
||||||
DWORD VisibleToTeam;
|
DWORD VisibleToTeam;
|
||||||
|
@ -1080,7 +1080,6 @@ public:
|
||||||
TObjPtr<AActor> alternative; // (Un)Morphed actors stored here. Those with the MF_UNMORPHED flag are the originals.
|
TObjPtr<AActor> alternative; // (Un)Morphed actors stored here. Those with the MF_UNMORPHED flag are the originals.
|
||||||
TObjPtr<AActor> tracer; // Thing being chased/attacked for tracers
|
TObjPtr<AActor> tracer; // Thing being chased/attacked for tracers
|
||||||
TObjPtr<AActor> master; // Thing which spawned this one (prevents mutual attacks)
|
TObjPtr<AActor> master; // Thing which spawned this one (prevents mutual attacks)
|
||||||
double Floorclip; // value to use for floor clipping
|
|
||||||
|
|
||||||
int tid; // thing identifier
|
int tid; // thing identifier
|
||||||
int special; // special
|
int special; // special
|
||||||
|
@ -1143,7 +1142,8 @@ public:
|
||||||
BYTE smokecounter;
|
BYTE smokecounter;
|
||||||
BYTE FloatBobPhase;
|
BYTE FloatBobPhase;
|
||||||
BYTE FriendPlayer; // [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc)
|
BYTE FriendPlayer; // [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc)
|
||||||
DWORD Translation;
|
PalEntry BloodColor;
|
||||||
|
DWORD BloodTranslation;
|
||||||
|
|
||||||
// [RH] Stuff that used to be part of an Actor Info
|
// [RH] Stuff that used to be part of an Actor Info
|
||||||
FSoundIDNoInit SeeSound;
|
FSoundIDNoInit SeeSound;
|
||||||
|
|
|
@ -125,6 +125,8 @@ public:
|
||||||
|
|
||||||
int crouchsprite;
|
int crouchsprite;
|
||||||
int MaxHealth;
|
int MaxHealth;
|
||||||
|
int BonusHealth;
|
||||||
|
|
||||||
int MugShotMaxHealth;
|
int MugShotMaxHealth;
|
||||||
int RunHealth;
|
int RunHealth;
|
||||||
int PlayerFlags;
|
int PlayerFlags;
|
||||||
|
|
|
@ -665,7 +665,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
|
||||||
bool isPicnumOverride = thing->picnum.isValid();
|
bool isPicnumOverride = thing->picnum.isValid();
|
||||||
|
|
||||||
// Don't waste time projecting sprites that are definitely not visible.
|
// Don't waste time projecting sprites that are definitely not visible.
|
||||||
if ((thing->sprite == 0 && !isPicnumOverride) || !thing->IsVisibleToPlayer() || !thing->IsInsideVisibleAngles())
|
if ((thing->sprite == 0 && !isPicnumOverride) || !thing->IsVisibleToPlayer() || ((thing->renderflags & RF_MASKROTATION) && !thing->IsInsideVisibleAngles()))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -295,7 +295,6 @@ void PClassActor::DeriveData(PClass *newclass)
|
||||||
PClassActor *newa = static_cast<PClassActor *>(newclass);
|
PClassActor *newa = static_cast<PClassActor *>(newclass);
|
||||||
|
|
||||||
newa->DefaultStateUsage = DefaultStateUsage;
|
newa->DefaultStateUsage = DefaultStateUsage;
|
||||||
newa->BloodColor = BloodColor;
|
|
||||||
newa->distancecheck = distancecheck;
|
newa->distancecheck = distancecheck;
|
||||||
|
|
||||||
newa->DropItems = DropItems;
|
newa->DropItems = DropItems;
|
||||||
|
|
|
@ -290,8 +290,6 @@ public:
|
||||||
|
|
||||||
TArray<PClassActor *> VisibleToPlayerClass;
|
TArray<PClassActor *> VisibleToPlayerClass;
|
||||||
|
|
||||||
PalEntry BloodColor; // Colorized blood
|
|
||||||
|
|
||||||
FDropItem *DropItems;
|
FDropItem *DropItems;
|
||||||
FString SourceLumpName;
|
FString SourceLumpName;
|
||||||
FIntCVar *distancecheck;
|
FIntCVar *distancecheck;
|
||||||
|
|
|
@ -1330,7 +1330,7 @@ static int CheckInventory (AActor *activator, const char *type, bool max)
|
||||||
if (max)
|
if (max)
|
||||||
{
|
{
|
||||||
if (activator->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
|
if (activator->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
|
||||||
return static_cast<APlayerPawn *>(activator)->MaxHealth;
|
return static_cast<APlayerPawn *>(activator)->GetMaxHealth();
|
||||||
else
|
else
|
||||||
return activator->SpawnHealth();
|
return activator->SpawnHealth();
|
||||||
}
|
}
|
||||||
|
@ -3939,7 +3939,7 @@ int DLevelScript::GetActorProperty (int tid, int property)
|
||||||
case APROP_Dormant: return !!(actor->flags2 & MF2_DORMANT);
|
case APROP_Dormant: return !!(actor->flags2 & MF2_DORMANT);
|
||||||
case APROP_SpawnHealth: if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
|
case APROP_SpawnHealth: if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
|
||||||
{
|
{
|
||||||
return static_cast<APlayerPawn *>(actor)->MaxHealth;
|
return static_cast<APlayerPawn *>(actor)->GetMaxHealth();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -2580,8 +2580,7 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags)
|
||||||
else if (flags & SIXF_USEBLOODCOLOR)
|
else if (flags & SIXF_USEBLOODCOLOR)
|
||||||
{
|
{
|
||||||
// [XA] Use the spawning actor's BloodColor to translate the newly-spawned object.
|
// [XA] Use the spawning actor's BloodColor to translate the newly-spawned object.
|
||||||
PalEntry bloodcolor = self->GetBloodColor();
|
mo->Translation = self->BloodTranslation;
|
||||||
mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flags & SIXF_TRANSFERPOINTERS)
|
if (flags & SIXF_TRANSFERPOINTERS)
|
||||||
|
|
|
@ -640,6 +640,7 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
|
||||||
floor->m_Delay = delay;
|
floor->m_Delay = delay;
|
||||||
floor->m_PauseTime = 0;
|
floor->m_PauseTime = 0;
|
||||||
floor->m_StepTime = floor->m_PerStepTime = persteptime;
|
floor->m_StepTime = floor->m_PerStepTime = persteptime;
|
||||||
|
floor->m_Instant = false;
|
||||||
|
|
||||||
floor->m_Crush = (usespecials & DFloor::stairCrush) ? 10 : -1; //jff 2/27/98 fix uninitialized crush field
|
floor->m_Crush = (usespecials & DFloor::stairCrush) ? 10 : -1; //jff 2/27/98 fix uninitialized crush field
|
||||||
floor->m_Hexencrush = false;
|
floor->m_Hexencrush = false;
|
||||||
|
@ -755,6 +756,7 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
|
||||||
//jff 2/27/98 fix uninitialized crush field
|
//jff 2/27/98 fix uninitialized crush field
|
||||||
floor->m_Crush = (!(usespecials & DFloor::stairUseSpecials) && speed == 4) ? 10 : -1; //jff 2/27/98 fix uninitialized crush field
|
floor->m_Crush = (!(usespecials & DFloor::stairUseSpecials) && speed == 4) ? 10 : -1; //jff 2/27/98 fix uninitialized crush field
|
||||||
floor->m_Hexencrush = false;
|
floor->m_Hexencrush = false;
|
||||||
|
floor->m_Instant = false;
|
||||||
floor->m_ResetCount = reset; // [RH] Tics until reset (0 if never)
|
floor->m_ResetCount = reset; // [RH] Tics until reset (0 if never)
|
||||||
floor->m_OrgDist = sec->floorplane.fD(); // [RH] Height to reset to
|
floor->m_OrgDist = sec->floorplane.fD(); // [RH] Height to reset to
|
||||||
}
|
}
|
||||||
|
@ -817,6 +819,7 @@ bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed)
|
||||||
floor->m_Direction = 1;
|
floor->m_Direction = 1;
|
||||||
floor->m_Sector = s2;
|
floor->m_Sector = s2;
|
||||||
floor->m_Speed = slimespeed;
|
floor->m_Speed = slimespeed;
|
||||||
|
floor->m_Instant = false;
|
||||||
floor->m_Texture = s3->GetTexture(sector_t::floor);
|
floor->m_Texture = s3->GetTexture(sector_t::floor);
|
||||||
floor->m_NewSpecial.Clear();
|
floor->m_NewSpecial.Clear();
|
||||||
height = s3->FindHighestFloorPoint (&spot);
|
height = s3->FindHighestFloorPoint (&spot);
|
||||||
|
@ -831,6 +834,7 @@ bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed)
|
||||||
floor->m_Direction = -1;
|
floor->m_Direction = -1;
|
||||||
floor->m_Sector = s1;
|
floor->m_Sector = s1;
|
||||||
floor->m_Speed = pillarspeed;
|
floor->m_Speed = pillarspeed;
|
||||||
|
floor->m_Instant = false;
|
||||||
height = s3->FindHighestFloorPoint (&spot);
|
height = s3->FindHighestFloorPoint (&spot);
|
||||||
floor->m_FloorDestDist = s1->floorplane.PointToDist (spot, height);
|
floor->m_FloorDestDist = s1->floorplane.PointToDist (spot, height);
|
||||||
floor->StartFloorSound ();
|
floor->StartFloorSound ();
|
||||||
|
|
|
@ -253,6 +253,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (message == nullptr) message = messagename; // fallback to defaults if possible.
|
if (message == nullptr) message = messagename; // fallback to defaults if possible.
|
||||||
|
if (attacker == nullptr) attacker = self; // world
|
||||||
if (attacker->player == nullptr) attacker = self; // for the message creation
|
if (attacker->player == nullptr) attacker = self; // for the message creation
|
||||||
|
|
||||||
if (message != NULL && message[0] == '$')
|
if (message != NULL && message[0] == '$')
|
||||||
|
|
|
@ -4803,7 +4803,7 @@ void P_TraceBleed(int damage, const DVector3 &pos, AActor *actor, DAngle angle,
|
||||||
{
|
{
|
||||||
if (bleedtrace.HitType == TRACE_HitWall)
|
if (bleedtrace.HitType == TRACE_HitWall)
|
||||||
{
|
{
|
||||||
PalEntry bloodcolor = actor->GetBloodColor();
|
PalEntry bloodcolor = actor->BloodColor;
|
||||||
if (bloodcolor != 0)
|
if (bloodcolor != 0)
|
||||||
{
|
{
|
||||||
bloodcolor.r >>= 1; // the full color is too bright for blood decals
|
bloodcolor.r >>= 1; // the full color is too bright for blood decals
|
||||||
|
@ -5994,7 +5994,6 @@ void P_DoCrunch(AActor *thing, FChangePosition *cpos)
|
||||||
{
|
{
|
||||||
if (!(thing->flags&MF_NOBLOOD))
|
if (!(thing->flags&MF_NOBLOOD))
|
||||||
{
|
{
|
||||||
PalEntry bloodcolor = thing->GetBloodColor();
|
|
||||||
PClassActor *bloodcls = thing->GetBloodType();
|
PClassActor *bloodcls = thing->GetBloodType();
|
||||||
|
|
||||||
P_TraceBleed (newdam > 0 ? newdam : cpos->crushchange, thing);
|
P_TraceBleed (newdam > 0 ? newdam : cpos->crushchange, thing);
|
||||||
|
@ -6006,9 +6005,9 @@ void P_DoCrunch(AActor *thing, FChangePosition *cpos)
|
||||||
|
|
||||||
mo->Vel.X = pr_crunch.Random2() / 16.;
|
mo->Vel.X = pr_crunch.Random2() / 16.;
|
||||||
mo->Vel.Y = pr_crunch.Random2() / 16.;
|
mo->Vel.Y = pr_crunch.Random2() / 16.;
|
||||||
if (bloodcolor != 0 && !(mo->flags2 & MF2_DONTTRANSLATE))
|
if (thing->BloodTranslation != 0 && !(mo->flags2 & MF2_DONTTRANSLATE))
|
||||||
{
|
{
|
||||||
mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
mo->Translation = thing->BloodTranslation;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(cl_bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE;
|
if (!(cl_bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE;
|
||||||
|
@ -6017,7 +6016,7 @@ void P_DoCrunch(AActor *thing, FChangePosition *cpos)
|
||||||
DAngle an = (M_Random() - 128) * (360./256);
|
DAngle an = (M_Random() - 128) * (360./256);
|
||||||
if (cl_bloodtype >= 1)
|
if (cl_bloodtype >= 1)
|
||||||
{
|
{
|
||||||
P_DrawSplash2(32, thing->PosPlusZ(thing->Height/2), an, 2, bloodcolor);
|
P_DrawSplash2(32, thing->PosPlusZ(thing->Height/2), an, 2, thing->BloodColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (thing->CrushPainSound != 0 && !S_GetSoundPlayingInfo(thing, thing->CrushPainSound))
|
if (thing->CrushPainSound != 0 && !S_GetSoundPlayingInfo(thing, thing->CrushPainSound))
|
||||||
|
|
|
@ -316,8 +316,8 @@ DEFINE_FIELD(AActor, RadiusDamageFactor)
|
||||||
DEFINE_FIELD(AActor, SelfDamageFactor)
|
DEFINE_FIELD(AActor, SelfDamageFactor)
|
||||||
DEFINE_FIELD(AActor, StealthAlpha)
|
DEFINE_FIELD(AActor, StealthAlpha)
|
||||||
DEFINE_FIELD(AActor, WoundHealth)
|
DEFINE_FIELD(AActor, WoundHealth)
|
||||||
|
DEFINE_FIELD(AActor, BloodColor)
|
||||||
//DEFINE_FIELD(PClassActor, BloodColor)
|
DEFINE_FIELD(AActor, BloodTranslation)
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -409,6 +409,8 @@ void AActor::Serialize(FSerializer &arc)
|
||||||
A("inventoryid", InventoryID)
|
A("inventoryid", InventoryID)
|
||||||
A("floatbobphase", FloatBobPhase)
|
A("floatbobphase", FloatBobPhase)
|
||||||
A("translation", Translation)
|
A("translation", Translation)
|
||||||
|
A("bloodcolor", BloodColor)
|
||||||
|
A("bloodtranslation", BloodTranslation)
|
||||||
A("seesound", SeeSound)
|
A("seesound", SeeSound)
|
||||||
A("attacksound", AttackSound)
|
A("attacksound", AttackSound)
|
||||||
A("paimsound", PainSound)
|
A("paimsound", PainSound)
|
||||||
|
@ -1338,7 +1340,7 @@ bool P_GiveBody(AActor *actor, int num, int max)
|
||||||
{
|
{
|
||||||
if (!(player->MorphStyle & MORPH_ADDSTAMINA))
|
if (!(player->MorphStyle & MORPH_ADDSTAMINA))
|
||||||
{
|
{
|
||||||
max -= player->mo->stamina;
|
max -= player->mo->stamina + player->mo->BonusHealth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // old health behaviour
|
else // old health behaviour
|
||||||
|
@ -1346,7 +1348,7 @@ bool P_GiveBody(AActor *actor, int num, int max)
|
||||||
max = MAXMORPHHEALTH;
|
max = MAXMORPHHEALTH;
|
||||||
if (player->MorphStyle & MORPH_ADDSTAMINA)
|
if (player->MorphStyle & MORPH_ADDSTAMINA)
|
||||||
{
|
{
|
||||||
max += player->mo->stamina;
|
max += player->mo->stamina + player->mo->BonusHealth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1665,8 +1667,7 @@ bool AActor::Grind(bool items)
|
||||||
if (isgeneric) // Not a custom crush state, so colorize it appropriately.
|
if (isgeneric) // Not a custom crush state, so colorize it appropriately.
|
||||||
{
|
{
|
||||||
S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE);
|
S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE);
|
||||||
PalEntry bloodcolor = GetBloodColor();
|
Translation = BloodTranslation;
|
||||||
if (bloodcolor!=0) Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1707,10 +1708,7 @@ bool AActor::Grind(bool items)
|
||||||
gib->Alpha = Alpha;
|
gib->Alpha = Alpha;
|
||||||
gib->Height = 0;
|
gib->Height = 0;
|
||||||
gib->radius = 0;
|
gib->radius = 0;
|
||||||
|
gib->Translation = BloodTranslation;
|
||||||
PalEntry bloodcolor = GetBloodColor();
|
|
||||||
if (bloodcolor != 0)
|
|
||||||
gib->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
|
||||||
}
|
}
|
||||||
S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE);
|
S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE);
|
||||||
}
|
}
|
||||||
|
@ -3510,7 +3508,7 @@ int AActor::GetMissileDamage (int mask, int add)
|
||||||
|
|
||||||
void AActor::Howl ()
|
void AActor::Howl ()
|
||||||
{
|
{
|
||||||
FSoundID howl = IntVar(NAME_HowlSound);
|
FSoundID howl = SoundVar(NAME_HowlSound);
|
||||||
if (!S_IsActorPlayingSomething(this, CHAN_BODY, howl))
|
if (!S_IsActorPlayingSomething(this, CHAN_BODY, howl))
|
||||||
{
|
{
|
||||||
S_Sound (this, CHAN_BODY, howl, 1, ATTN_NORM);
|
S_Sound (this, CHAN_BODY, howl, 1, ATTN_NORM);
|
||||||
|
@ -6051,7 +6049,6 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnPuff)
|
||||||
void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *originator)
|
void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *originator)
|
||||||
{
|
{
|
||||||
AActor *th;
|
AActor *th;
|
||||||
PalEntry bloodcolor = originator->GetBloodColor();
|
|
||||||
PClassActor *bloodcls = originator->GetBloodType();
|
PClassActor *bloodcls = originator->GetBloodType();
|
||||||
DVector3 pos = pos1;
|
DVector3 pos = pos1;
|
||||||
pos.Z += pr_spawnblood.Random2() / 64.;
|
pos.Z += pr_spawnblood.Random2() / 64.;
|
||||||
|
@ -6076,9 +6073,9 @@ void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *origina
|
||||||
th->tics = 1;
|
th->tics = 1;
|
||||||
}
|
}
|
||||||
// colorize the blood
|
// colorize the blood
|
||||||
if (bloodcolor != 0 && !(th->flags2 & MF2_DONTTRANSLATE))
|
if (!(th->flags2 & MF2_DONTTRANSLATE))
|
||||||
{
|
{
|
||||||
th->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
th->Translation = originator->BloodTranslation;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Moved out of the blood actor so that replacing blood is easier
|
// Moved out of the blood actor so that replacing blood is easier
|
||||||
|
@ -6135,7 +6132,7 @@ void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *origina
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bloodtype >= 1)
|
if (bloodtype >= 1)
|
||||||
P_DrawSplash2 (40, pos, dir, 2, bloodcolor);
|
P_DrawSplash2 (40, pos, dir, 2, originator->BloodColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, SpawnBlood)
|
DEFINE_ACTION_FUNCTION(AActor, SpawnBlood)
|
||||||
|
@ -6159,7 +6156,6 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnBlood)
|
||||||
|
|
||||||
void P_BloodSplatter (const DVector3 &pos, AActor *originator, DAngle hitangle)
|
void P_BloodSplatter (const DVector3 &pos, AActor *originator, DAngle hitangle)
|
||||||
{
|
{
|
||||||
PalEntry bloodcolor = originator->GetBloodColor();
|
|
||||||
PClassActor *bloodcls = originator->GetBloodType(1);
|
PClassActor *bloodcls = originator->GetBloodType(1);
|
||||||
|
|
||||||
int bloodtype = cl_bloodtype;
|
int bloodtype = cl_bloodtype;
|
||||||
|
@ -6178,16 +6174,16 @@ void P_BloodSplatter (const DVector3 &pos, AActor *originator, DAngle hitangle)
|
||||||
mo->Vel.Z = 3;
|
mo->Vel.Z = 3;
|
||||||
|
|
||||||
// colorize the blood!
|
// colorize the blood!
|
||||||
if (bloodcolor!=0 && !(mo->flags2 & MF2_DONTTRANSLATE))
|
if (!(mo->flags2 & MF2_DONTTRANSLATE))
|
||||||
{
|
{
|
||||||
mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
mo->Translation = originator->BloodTranslation;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE;
|
if (!(bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE;
|
||||||
}
|
}
|
||||||
if (bloodtype >= 1)
|
if (bloodtype >= 1)
|
||||||
{
|
{
|
||||||
P_DrawSplash2 (40, pos, hitangle-180., 2, bloodcolor);
|
P_DrawSplash2 (40, pos, hitangle-180., 2, originator->BloodColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6199,7 +6195,6 @@ void P_BloodSplatter (const DVector3 &pos, AActor *originator, DAngle hitangle)
|
||||||
|
|
||||||
void P_BloodSplatter2 (const DVector3 &pos, AActor *originator, DAngle hitangle)
|
void P_BloodSplatter2 (const DVector3 &pos, AActor *originator, DAngle hitangle)
|
||||||
{
|
{
|
||||||
PalEntry bloodcolor = originator->GetBloodColor();
|
|
||||||
PClassActor *bloodcls = originator->GetBloodType(2);
|
PClassActor *bloodcls = originator->GetBloodType(2);
|
||||||
|
|
||||||
int bloodtype = cl_bloodtype;
|
int bloodtype = cl_bloodtype;
|
||||||
|
@ -6220,16 +6215,16 @@ void P_BloodSplatter2 (const DVector3 &pos, AActor *originator, DAngle hitangle)
|
||||||
mo->target = originator;
|
mo->target = originator;
|
||||||
|
|
||||||
// colorize the blood!
|
// colorize the blood!
|
||||||
if (bloodcolor != 0 && !(mo->flags2 & MF2_DONTTRANSLATE))
|
if (!(mo->flags2 & MF2_DONTTRANSLATE))
|
||||||
{
|
{
|
||||||
mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
mo->Translation = originator->BloodTranslation;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE;
|
if (!(bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE;
|
||||||
}
|
}
|
||||||
if (bloodtype >= 1)
|
if (bloodtype >= 1)
|
||||||
{
|
{
|
||||||
P_DrawSplash2(40, pos + add, hitangle - 180., 2, bloodcolor);
|
P_DrawSplash2(40, pos + add, hitangle - 180., 2, originator->BloodColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6255,7 +6250,6 @@ DEFINE_ACTION_FUNCTION(AActor, BloodSplatter)
|
||||||
|
|
||||||
void P_RipperBlood (AActor *mo, AActor *bleeder)
|
void P_RipperBlood (AActor *mo, AActor *bleeder)
|
||||||
{
|
{
|
||||||
PalEntry bloodcolor = bleeder->GetBloodColor();
|
|
||||||
PClassActor *bloodcls = bleeder->GetBloodType();
|
PClassActor *bloodcls = bleeder->GetBloodType();
|
||||||
|
|
||||||
double xo = pr_ripperblood.Random2() / 16.;
|
double xo = pr_ripperblood.Random2() / 16.;
|
||||||
|
@ -6281,16 +6275,16 @@ void P_RipperBlood (AActor *mo, AActor *bleeder)
|
||||||
th->tics += pr_ripperblood () & 3;
|
th->tics += pr_ripperblood () & 3;
|
||||||
|
|
||||||
// colorize the blood!
|
// colorize the blood!
|
||||||
if (bloodcolor!=0 && !(th->flags2 & MF2_DONTTRANSLATE))
|
if (!(th->flags2 & MF2_DONTTRANSLATE))
|
||||||
{
|
{
|
||||||
th->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
th->Translation = bleeder->BloodTranslation;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(bloodtype <= 1)) th->renderflags |= RF_INVISIBLE;
|
if (!(bloodtype <= 1)) th->renderflags |= RF_INVISIBLE;
|
||||||
}
|
}
|
||||||
if (bloodtype >= 1)
|
if (bloodtype >= 1)
|
||||||
{
|
{
|
||||||
P_DrawSplash2(28, pos, bleeder->AngleTo(mo) + 180., 0, bloodcolor);
|
P_DrawSplash2(28, pos, bleeder->AngleTo(mo) + 180., 0, bleeder->BloodColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -781,6 +781,7 @@ void APlayerPawn::Serialize(FSerializer &arc)
|
||||||
|
|
||||||
arc("jumpz", JumpZ, def->JumpZ)
|
arc("jumpz", JumpZ, def->JumpZ)
|
||||||
("maxhealth", MaxHealth, def->MaxHealth)
|
("maxhealth", MaxHealth, def->MaxHealth)
|
||||||
|
("bonushealth", BonusHealth, def->BonusHealth)
|
||||||
("runhealth", RunHealth, def->RunHealth)
|
("runhealth", RunHealth, def->RunHealth)
|
||||||
("spawnmask", SpawnMask, def->SpawnMask)
|
("spawnmask", SpawnMask, def->SpawnMask)
|
||||||
("forwardmove1", ForwardMove1, def->ForwardMove1)
|
("forwardmove1", ForwardMove1, def->ForwardMove1)
|
||||||
|
@ -1353,7 +1354,7 @@ const char *APlayerPawn::GetSoundClass() const
|
||||||
int APlayerPawn::GetMaxHealth(bool withupgrades) const
|
int APlayerPawn::GetMaxHealth(bool withupgrades) const
|
||||||
{
|
{
|
||||||
int ret = MaxHealth > 0? MaxHealth : ((i_compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth);
|
int ret = MaxHealth > 0? MaxHealth : ((i_compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth);
|
||||||
if (withupgrades) ret += stamina;
|
if (withupgrades) ret += stamina + BonusHealth;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3346,6 +3347,7 @@ bool P_IsPlayerTotallyFrozen(const player_t *player)
|
||||||
|
|
||||||
DEFINE_FIELD(APlayerPawn, crouchsprite)
|
DEFINE_FIELD(APlayerPawn, crouchsprite)
|
||||||
DEFINE_FIELD(APlayerPawn, MaxHealth)
|
DEFINE_FIELD(APlayerPawn, MaxHealth)
|
||||||
|
DEFINE_FIELD(APlayerPawn, BonusHealth)
|
||||||
DEFINE_FIELD(APlayerPawn, MugShotMaxHealth)
|
DEFINE_FIELD(APlayerPawn, MugShotMaxHealth)
|
||||||
DEFINE_FIELD(APlayerPawn, RunHealth)
|
DEFINE_FIELD(APlayerPawn, RunHealth)
|
||||||
DEFINE_FIELD(APlayerPawn, PlayerFlags)
|
DEFINE_FIELD(APlayerPawn, PlayerFlags)
|
||||||
|
|
|
@ -218,8 +218,11 @@ bool FZipFile::Open(bool quiet)
|
||||||
char *dirptr = (char*)directory;
|
char *dirptr = (char*)directory;
|
||||||
FZipLump *lump_p = Lumps;
|
FZipLump *lump_p = Lumps;
|
||||||
|
|
||||||
// Check if all files have the same prefix so that this can be stripped out.
|
|
||||||
FString name0;
|
FString name0;
|
||||||
|
bool foundspeciallump = false;
|
||||||
|
|
||||||
|
// Check if all files have the same prefix so that this can be stripped out.
|
||||||
|
// This will only be done if there is either a MAPINFO, ZMAPINFO or GAMEINFO lump in the subdirectory, denoting a ZDoom mod.
|
||||||
if (NumLumps > 1) for (DWORD i = 0; i < NumLumps; i++)
|
if (NumLumps > 1) for (DWORD i = 0; i < NumLumps; i++)
|
||||||
{
|
{
|
||||||
FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr;
|
FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr;
|
||||||
|
@ -251,6 +254,7 @@ bool FZipFile::Open(bool quiet)
|
||||||
!name.Compare("voxels/") ||
|
!name.Compare("voxels/") ||
|
||||||
!name.Compare("colormaps/") ||
|
!name.Compare("colormaps/") ||
|
||||||
!name.Compare("acs/") ||
|
!name.Compare("acs/") ||
|
||||||
|
!name.Compare("maps/") ||
|
||||||
!name.Compare("voices/") ||
|
!name.Compare("voices/") ||
|
||||||
!name.Compare("patches/") ||
|
!name.Compare("patches/") ||
|
||||||
!name.Compare("graphics/") ||
|
!name.Compare("graphics/") ||
|
||||||
|
@ -266,6 +270,23 @@ bool FZipFile::Open(bool quiet)
|
||||||
name0 = "";
|
name0 = "";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if (!foundspeciallump)
|
||||||
|
{
|
||||||
|
// at least one of the more common definition lumps must be present.
|
||||||
|
if (name.IndexOf(name0 + "mapinfo") == 0) foundspeciallump = true;
|
||||||
|
else if (name.IndexOf(name0 + "zmapinfo") == 0) foundspeciallump = true;
|
||||||
|
else if (name.IndexOf(name0 + "gameinfo") == 0) foundspeciallump = true;
|
||||||
|
else if (name.IndexOf(name0 + "sndinfo") == 0) foundspeciallump = true;
|
||||||
|
else if (name.IndexOf(name0 + "sbarinfo") == 0) foundspeciallump = true;
|
||||||
|
else if (name.IndexOf(name0 + "menudef") == 0) foundspeciallump = true;
|
||||||
|
else if (name.IndexOf(name0 + "gldefs") == 0) foundspeciallump = true;
|
||||||
|
else if (name.IndexOf(name0 + "animdefs") == 0) foundspeciallump = true;
|
||||||
|
else if (name.IndexOf(name0 + "decorate.") == 0) foundspeciallump = true; // DECORATE is a common subdirectory name, so the check needs to be a bit different.
|
||||||
|
else if (name.Compare(name0 + "decorate") == 0) foundspeciallump = true;
|
||||||
|
else if (name.IndexOf(name0 + "zscript.") == 0) foundspeciallump = true; // same here.
|
||||||
|
else if (name.Compare(name0 + "zscript") == 0) foundspeciallump = true;
|
||||||
|
else if (name.Compare(name0 + "maps/") == 0) foundspeciallump = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -846,6 +846,7 @@ void FFunctionBuildList::Build()
|
||||||
{
|
{
|
||||||
int errorcount = 0;
|
int errorcount = 0;
|
||||||
int codesize = 0;
|
int codesize = 0;
|
||||||
|
int datasize = 0;
|
||||||
FILE *dump = nullptr;
|
FILE *dump = nullptr;
|
||||||
|
|
||||||
if (Args->CheckParm("-dumpdisasm")) dump = fopen("disasm.txt", "w");
|
if (Args->CheckParm("-dumpdisasm")) dump = fopen("disasm.txt", "w");
|
||||||
|
@ -927,6 +928,8 @@ void FFunctionBuildList::Build()
|
||||||
{
|
{
|
||||||
DumpFunction(dump, sfunc, item.PrintableName.GetChars(), (int)item.PrintableName.Len());
|
DumpFunction(dump, sfunc, item.PrintableName.GetChars(), (int)item.PrintableName.Len());
|
||||||
codesize += sfunc->CodeSize;
|
codesize += sfunc->CodeSize;
|
||||||
|
datasize += sfunc->LineInfoCount * sizeof(FStatementInfo) + sfunc->ExtraSpace + sfunc->NumKonstD * sizeof(int) +
|
||||||
|
sfunc->NumKonstA * sizeof(void*) + sfunc->NumKonstF * sizeof(double) + sfunc->NumKonstS * sizeof(FString);
|
||||||
}
|
}
|
||||||
sfunc->Unsafe = ctx.Unsafe;
|
sfunc->Unsafe = ctx.Unsafe;
|
||||||
}
|
}
|
||||||
|
@ -944,10 +947,11 @@ void FFunctionBuildList::Build()
|
||||||
}
|
}
|
||||||
if (dump != nullptr)
|
if (dump != nullptr)
|
||||||
{
|
{
|
||||||
fprintf(dump, "\n*************************************************************************\n%i code bytes\n", codesize * 4);
|
fprintf(dump, "\n*************************************************************************\n%i code bytes\n%i data bytes", codesize * 4, datasize);
|
||||||
fclose(dump);
|
fclose(dump);
|
||||||
}
|
}
|
||||||
FScriptPosition::StrictErrors = false;
|
FScriptPosition::StrictErrors = false;
|
||||||
mItems.Clear();
|
mItems.Clear();
|
||||||
|
mItems.ShrinkToFit();
|
||||||
FxAlloc.FreeAllBlocks();
|
FxAlloc.FreeAllBlocks();
|
||||||
}
|
}
|
|
@ -1053,10 +1053,9 @@ DEFINE_PROPERTY(bloodcolor, C, Actor)
|
||||||
{
|
{
|
||||||
PROP_COLOR_PARM(color, 0);
|
PROP_COLOR_PARM(color, 0);
|
||||||
|
|
||||||
PalEntry pe = color;
|
defaults->BloodColor = color;
|
||||||
pe.a = CreateBloodTranslation(pe);
|
defaults->BloodColor.a = 255; // a should not be 0.
|
||||||
assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
|
defaults->BloodTranslation = TRANSLATION(TRANSLATION_Blood, CreateBloodTranslation(color));
|
||||||
static_cast<PClassActor *>(info)->BloodColor = pe;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -194,7 +194,8 @@ class Actor : Thinker native
|
||||||
native double SelfDamageFactor;
|
native double SelfDamageFactor;
|
||||||
native double StealthAlpha;
|
native double StealthAlpha;
|
||||||
native int WoundHealth; // Health needed to enter wound state
|
native int WoundHealth; // Health needed to enter wound state
|
||||||
//native color BloodColor; // won't be accessible for now because it needs refactoring to remove the 255-translations limit.
|
native readonly color BloodColor;
|
||||||
|
native readonly int BloodTranslation;
|
||||||
|
|
||||||
meta String Obituary; // Player was killed by this actor
|
meta String Obituary; // Player was killed by this actor
|
||||||
meta String HitObituary; // Player was killed by this actor in melee
|
meta String HitObituary; // Player was killed by this actor in melee
|
||||||
|
|
|
@ -1009,6 +1009,13 @@ enum ERaise
|
||||||
RF_NOCHECKPOSITION = 2
|
RF_NOCHECKPOSITION = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum eFogParm
|
||||||
|
{
|
||||||
|
FOGP_DENSITY = 0,
|
||||||
|
FOGP_OUTSIDEDENSITY = 1,
|
||||||
|
FOGP_SKYFOG = 2,
|
||||||
|
}
|
||||||
|
|
||||||
enum ETeleport
|
enum ETeleport
|
||||||
{
|
{
|
||||||
TELF_DESTFOG = 1,
|
TELF_DESTFOG = 1,
|
||||||
|
|
|
@ -86,8 +86,36 @@ class Health : Inventory
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MaxHealth : Health
|
||||||
|
{
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// TryPickup
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override bool TryPickup (in out Actor other)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
int savedAmount = MaxAmount;
|
||||||
|
let player = PlayerPawn(other);
|
||||||
|
MaxAmount = Health;
|
||||||
|
if (player)
|
||||||
|
{
|
||||||
|
if (player.BonusHealth < savedAmount)
|
||||||
|
{
|
||||||
|
player.BonusHealth = min(player.BonusHealth + Amount, savedAmount);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
MaxAmount += player.BonusHealth;
|
||||||
|
}
|
||||||
|
success |= Super.TryPickup(other);
|
||||||
|
MaxAmount = savedAmount;
|
||||||
|
if (success) GoAwayAndDie();
|
||||||
|
return success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HealthPickup : Inventory
|
class HealthPickup : Inventory
|
||||||
|
|
|
@ -3,6 +3,7 @@ class PlayerPawn : Actor native
|
||||||
|
|
||||||
native int crouchsprite;
|
native int crouchsprite;
|
||||||
native int MaxHealth;
|
native int MaxHealth;
|
||||||
|
native int BonusHealth;
|
||||||
native int MugShotMaxHealth;
|
native int MugShotMaxHealth;
|
||||||
native int RunHealth;
|
native int RunHealth;
|
||||||
native int PlayerFlags;
|
native int PlayerFlags;
|
||||||
|
|
|
@ -95,7 +95,7 @@ class Programmer : Actor
|
||||||
A_PlaySound("programmer/clank", CHAN_WEAPON);
|
A_PlaySound("programmer/clank", CHAN_WEAPON);
|
||||||
|
|
||||||
int damage = ((random[Programmer]() % 10) + 1) * 6;
|
int damage = ((random[Programmer]() % 10) + 1) * 6;
|
||||||
int newdam = DamageMobj (self, self, damage, 'Melee');
|
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue