This commit is contained in:
Christoph Oelckers 2016-07-16 19:57:09 +02:00
commit bce9929c22
13 changed files with 205 additions and 30 deletions

View file

@ -543,6 +543,7 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
# C++11 support using SDKs 10.7 and 10.8.
if ( APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang" )
set( CMAKE_CXX_FLAGS "-stdlib=libc++ ${CMAKE_CXX_FLAGS}" )
set( CMAKE_EXE_LINKER_FLAGS "-stdlib=libc++ ${CMAKE_EXE_LINKER_FLAGS}" )
endif ()
# Remove extra warnings when using the official DirectX headers.

View file

@ -147,7 +147,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit)
{
spit->special2 = 0;
}
else if (fabs(spit->Vel.X) > fabs(spit->Vel.Y))
else if (fabs(spit->Vel.Y) > fabs(spit->Vel.X))
{
spit->special2 = int((targ->Y() - self->Y()) / spit->Vel.Y);
}

View file

@ -1127,12 +1127,27 @@ void APowerWeaponLevel2::InitEffect ()
assert (sister->SisterWeapon == weapon);
Owner->player->ReadyWeapon = sister;
if (weapon->GetReadyState() != sister->GetReadyState())
{
Owner->player->ReadyWeapon = sister;
P_SetPsprite(Owner->player, PSP_WEAPON, sister->GetReadyState());
}
else
{
DPSprite *psp = Owner->player->FindPSprite(PSP_WEAPON);
if (psp != nullptr && psp->GetCaller() == Owner->player->ReadyWeapon)
{
// If the weapon changes but the state does not, we have to manually change the PSprite's caller here.
psp->SetCaller(sister);
Owner->player->ReadyWeapon = sister;
}
else
{
// Something went wrong. Initiate a regular weapon change.
Owner->player->PendingWeapon = sister;
}
}
}
//===========================================================================

View file

@ -642,8 +642,19 @@ void AWeapon::EndPowerup ()
}
else
{
DPSprite *psp = Owner->player->FindPSprite(PSP_WEAPON);
if (psp != nullptr && psp->GetCaller() == Owner->player->ReadyWeapon)
{
// If the weapon changes but the state does not, we have to manually change the PSprite's caller here.
psp->SetCaller(SisterWeapon);
Owner->player->ReadyWeapon = SisterWeapon;
}
else
{
// Something went wrong. Initiate a regular weapon change.
Owner->player->PendingWeapon = SisterWeapon;
}
}
}
}

View file

@ -81,6 +81,7 @@ CVAR (Int , hud_showtime, 0, CVAR_ARCHIVE); // Show time on HUD
CVAR (Int , hud_timecolor, CR_GOLD,CVAR_ARCHIVE); // Color of in-game time on HUD
CVAR (Int , hud_showlag, 0, CVAR_ARCHIVE); // Show input latency (maketic - gametic difference)
CVAR (Int, hud_ammo_order, 0, CVAR_ARCHIVE); // ammo image and text order
CVAR (Int, hud_ammo_red, 25, CVAR_ARCHIVE) // ammo percent less than which status is red
CVAR (Int, hud_ammo_yellow, 50, CVAR_ARCHIVE) // ammo percent less is yellow more green
CVAR (Int, hud_health_red, 25, CVAR_ARCHIVE) // health amount less than which status is red
@ -586,9 +587,21 @@ static int DrawAmmo(player_t *CPlayer, int x, int y)
// ok, we got all ammo types. Now draw the list back to front (bottom to top)
int def_width = ConFont->StringWidth("000/000");
x-=def_width;
int yadd = ConFont->GetHeight();
int xtext = x - def_width;
int ximage = x;
if (hud_ammo_order > 0)
{
xtext -= 24;
ximage -= 20;
}
else
{
ximage -= def_width + 20;
}
for(i=orderedammos.Size()-1;i>=0;i--)
{
@ -613,8 +626,8 @@ static int DrawAmmo(player_t *CPlayer, int x, int y)
ammo < ( (maxammo * hud_ammo_red) / 100) ? CR_RED :
ammo < ( (maxammo * hud_ammo_yellow) / 100) ? CR_GOLD : CR_GREEN );
DrawHudText(ConFont, fontcolor, buf, x-tex_width, y+yadd, trans);
DrawImageToBox(TexMan[icon], x-20, y, 16, 8, trans);
DrawHudText(ConFont, fontcolor, buf, xtext-tex_width, y+yadd, trans);
DrawImageToBox(TexMan[icon], ximage, y, 16, 8, trans);
y-=10;
}
return y;

View file

@ -325,7 +325,8 @@ enum // P_LineAttack flags
{
LAF_ISMELEEATTACK = 1,
LAF_NORANDOMPUFFZ = 2,
LAF_NOIMPACTDECAL = 4
LAF_NOIMPACTDECAL = 4,
LAF_NOINTERACT = 8,
};
AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL);

View file

@ -4096,6 +4096,7 @@ static ETraceStatus CheckForActor(FTraceResults &res, void *userdata)
AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, FTranslatedLineTarget*victim, int *actualdamage)
{
bool nointeract = !!(flags & LAF_NOINTERACT);
DVector3 direction;
double shootz;
FTraceResults trace;
@ -4185,26 +4186,32 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
}
int tflags;
if (puffDefaults != NULL && puffDefaults->flags6 & MF6_NOTRIGGER) tflags = TRACE_NoSky;
if (nointeract || (puffDefaults && puffDefaults->flags6 & MF6_NOTRIGGER)) tflags = TRACE_NoSky;
else tflags = TRACE_NoSky | TRACE_Impact;
if (!Trace(t1->PosAtZ(shootz), t1->Sector, direction, distance, MF_SHOOTABLE,
ML_BLOCKEVERYTHING | ML_BLOCKHITSCAN, t1, trace, tflags, CheckForActor, &TData))
{ // hit nothing
if (puffDefaults == NULL)
{
}
else if (puffDefaults->ActiveSound)
if (!nointeract && puffDefaults && puffDefaults->ActiveSound)
{ // Play miss sound
S_Sound(t1, CHAN_WEAPON, puffDefaults->ActiveSound, 1, ATTN_NORM);
}
if (puffDefaults != NULL && puffDefaults->flags3 & MF3_ALWAYSPUFF)
// [MC] LAF_NOINTERACT guarantees puff spawning and returns it directly to the calling function.
// No damage caused, no sounds played, no blood splatters.
if (nointeract || (puffDefaults && puffDefaults->flags3 & MF3_ALWAYSPUFF))
{ // Spawn the puff anyway
puff = P_SpawnPuff(t1, pufftype, trace.HitPos, trace.SrcAngleFromTarget, trace.SrcAngleFromTarget, 2, puffFlags);
if (nointeract)
{
return puff;
}
}
else
{
return NULL;
return nullptr;
}
}
else
@ -4212,12 +4219,17 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
if (trace.HitType != TRACE_HitActor)
{
// position a bit closer for puffs
if (trace.HitType != TRACE_HitWall || ((trace.Line->special != Line_Horizon) || spawnSky))
if (nointeract || trace.HitType != TRACE_HitWall || ((trace.Line->special != Line_Horizon) || spawnSky))
{
DVector2 pos = P_GetOffsetPosition(trace.HitPos.X, trace.HitPos.Y, -trace.HitVector.X * 4, -trace.HitVector.Y * 4);
puff = P_SpawnPuff(t1, pufftype, DVector3(pos, trace.HitPos.Z - trace.HitVector.Z * 4), trace.SrcAngleFromTarget,
trace.SrcAngleFromTarget - 90, 0, puffFlags);
puff->radius = 1/65536.;
if (nointeract)
{
return puff;
}
}
// [RH] Spawn a decal
@ -4255,14 +4267,6 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
}
else
{
bool bloodsplatter = (t1->flags5 & MF5_BLOODSPLATTER) ||
(t1->player != NULL && t1->player->ReadyWeapon != NULL &&
(t1->player->ReadyWeapon->WeaponFlags & WIF_AXEBLOOD));
bool axeBlood = (t1->player != NULL &&
t1->player->ReadyWeapon != NULL &&
(t1->player->ReadyWeapon->WeaponFlags & WIF_AXEBLOOD));
// Hit a thing, so it could be either a puff or blood
DVector3 bleedpos = trace.HitPos;
// position a bit closer for puffs/blood if using compatibility mode.
@ -4275,7 +4279,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
}
// Spawn bullet puffs or blood spots, depending on target type.
if ((puffDefaults != NULL && puffDefaults->flags3 & MF3_PUFFONACTORS) ||
if (nointeract || (puffDefaults && puffDefaults->flags3 & MF3_PUFFONACTORS) ||
(trace.Actor->flags & MF_NOBLOOD) ||
(trace.Actor->flags2 & (MF2_INVULNERABLE | MF2_DORMANT)))
{
@ -4284,6 +4288,11 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
// We must pass the unreplaced puff type here
puff = P_SpawnPuff(t1, pufftype, bleedpos, trace.SrcAngleFromTarget, trace.SrcAngleFromTarget - 90, 2, puffFlags | PF_HITTHING, trace.Actor);
if (nointeract)
{
return puff;
}
}
// Allow puffs to inflict poison damage, so that hitscans can poison, too.
@ -4320,6 +4329,14 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
}
if (!(puffDefaults != NULL && puffDefaults->flags3&MF3_BLOODLESSIMPACT))
{
bool bloodsplatter = (t1->flags5 & MF5_BLOODSPLATTER) ||
(t1->player != nullptr && t1->player->ReadyWeapon != nullptr &&
(t1->player->ReadyWeapon->WeaponFlags & WIF_AXEBLOOD));
bool axeBlood = (t1->player != nullptr &&
t1->player->ReadyWeapon != nullptr &&
(t1->player->ReadyWeapon->WeaponFlags & WIF_AXEBLOOD));
if (!bloodsplatter && !axeBlood &&
!(trace.Actor->flags & MF_NOBLOOD) &&
!(trace.Actor->flags2 & (MF2_INVULNERABLE | MF2_DORMANT)))

View file

@ -77,6 +77,7 @@ public:
FState* GetState() const { return State; }
DPSprite* GetNext() { return Next; }
AActor* GetCaller() { return Caller; }
void SetCaller(AActor *newcaller) { Caller = newcaller; }
double x, y;
double oldx, oldy;

View file

@ -1622,8 +1622,13 @@ enum CBA_Flags
CBAF_EXPLICITANGLE = 4,
CBAF_NOPITCH = 8,
CBAF_NORANDOMPUFFZ = 16,
CBAF_PUFFTARGET = 32,
CBAF_PUFFMASTER = 64,
CBAF_PUFFTRACER = 128,
};
static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp, bool cba);
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack)
{
PARAM_SELF_PROLOGUE(AActor);
@ -1635,6 +1640,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack)
PARAM_FLOAT_OPT (range) { range = 0; }
PARAM_INT_OPT (flags) { flags = 0; }
PARAM_INT_OPT (ptr) { ptr = AAPTR_TARGET; }
PARAM_CLASS_OPT (missile, AActor) { missile = nullptr; }
PARAM_FLOAT_OPT (Spawnheight) { Spawnheight = 32; }
PARAM_FLOAT_OPT (Spawnofs_xy) { Spawnofs_xy = 0; }
AActor *ref = COPY_AAPTR(self, ptr);
@ -1679,7 +1687,30 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack)
if (!(flags & CBAF_NORANDOM))
damage *= ((pr_cabullet()%3)+1);
P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags);
AActor *puff = P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags);
if (missile != nullptr && pufftype != nullptr)
{
double x = Spawnofs_xy * angle.Cos();
double y = Spawnofs_xy * angle.Sin();
DVector3 pos = self->Pos();
self->SetXYZ(self->Vec3Offset(x, y, 0.));
AActor *proj = P_SpawnMissileAngleZSpeed(self, self->Z() + self->GetBobOffset() + Spawnheight, missile, self->Angles.Yaw, 0, GetDefaultByType(missile)->Speed, self, false);
self->SetXYZ(pos);
if (proj)
{
bool temp = (puff == nullptr);
if (!puff)
{
puff = P_LineAttack(self, angle, range, slope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT);
}
if (puff)
{
AimBulletMissile(proj, puff, flags, temp, true);
}
}
}
}
}
return 0;
@ -1808,8 +1839,46 @@ enum FB_Flags
FBF_NOPITCH = 8,
FBF_NOFLASH = 16,
FBF_NORANDOMPUFFZ = 32,
FBF_PUFFTARGET = 64,
FBF_PUFFMASTER = 128,
FBF_PUFFTRACER = 256,
};
static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp, bool cba)
{
if (proj && puff)
{
if (proj)
{
// FAF_BOTTOM = 1
// 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);
if (!temp)
{
if (cba)
{
if (flags & CBAF_PUFFTARGET) proj->target = puff;
if (flags & CBAF_PUFFMASTER) proj->master = puff;
if (flags & CBAF_PUFFTRACER) proj->tracer = puff;
}
else
{
if (flags & FBF_PUFFTARGET) proj->target = puff;
if (flags & FBF_PUFFMASTER) proj->master = puff;
if (flags & FBF_PUFFTRACER) proj->tracer = puff;
}
}
}
}
if (puff && temp)
{
puff->Destroy();
}
}
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets)
{
PARAM_ACTION_PROLOGUE;
@ -1817,9 +1886,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets)
PARAM_ANGLE (spread_z);
PARAM_INT (numbullets);
PARAM_INT (damageperbullet);
PARAM_CLASS_OPT (pufftype, AActor) { pufftype = NULL; }
PARAM_CLASS_OPT (pufftype, AActor) { pufftype = nullptr; }
PARAM_INT_OPT (flags) { flags = FBF_USEAMMO; }
PARAM_FLOAT_OPT (range) { range = 0; }
PARAM_CLASS_OPT (missile, AActor) { missile = nullptr; }
PARAM_FLOAT_OPT (Spawnheight) { Spawnheight = 0; }
PARAM_FLOAT_OPT (Spawnofs_xy) { Spawnofs_xy = 0; }
if (!self->player) return 0;
@ -1858,7 +1930,24 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets)
if (!(flags & FBF_NORANDOM))
damage *= ((pr_cwbullet()%3)+1);
P_LineAttack(self, bangle, range, bslope, damage, NAME_Hitscan, pufftype, laflags);
AActor *puff = P_LineAttack(self, bangle, range, bslope, damage, NAME_Hitscan, pufftype, laflags);
if (missile != nullptr)
{
bool temp = false;
DAngle ang = self->Angles.Yaw - 90;
DVector2 ofs = ang.ToVector(Spawnofs_xy);
AActor *proj = P_SpawnPlayerMissile(self, ofs.X, ofs.Y, Spawnheight, missile, bangle, nullptr, nullptr, false, true);
if (proj)
{
if (!puff)
{
temp = true;
puff = P_LineAttack(self, bangle, range, bslope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT);
}
AimBulletMissile(proj, puff, flags, temp, false);
}
}
}
else
{
@ -1885,7 +1974,24 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets)
if (!(flags & FBF_NORANDOM))
damage *= ((pr_cwbullet()%3)+1);
P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags);
AActor *puff = P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags);
if (missile != nullptr)
{
bool temp = false;
DAngle ang = self->Angles.Yaw - 90;
DVector2 ofs = ang.ToVector(Spawnofs_xy);
AActor *proj = P_SpawnPlayerMissile(self, ofs.X, ofs.Y, Spawnheight, missile, angle, nullptr, nullptr, false, true);
if (proj)
{
if (!puff)
{
temp = true;
puff = P_LineAttack(self, angle, range, slope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT);
}
AimBulletMissile(proj, puff, flags, temp, false);
}
}
}
}
return 0;

View file

@ -189,7 +189,7 @@ ACTOR Actor native //: Thinker
native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10);
native state A_Jump(int chance = 256, state label, ...);
native void A_CustomMissile(class<Actor> missiletype, float spawnheight = 32, float spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0, int ptr = AAPTR_TARGET);
native void A_CustomBulletAttack(float/*angle*/ spread_xy, float/*angle*/ spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET);
native void A_CustomBulletAttack(float/*angle*/ spread_xy, float/*angle*/ spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET, class<Actor> missile = "", float Spawnheight = 32, float Spawnofs_xy = 0);
native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, int aim = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float/*angle*/ spread_xy = 0, float/*angle*/ spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0);
native state A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT);
native state A_JumpIfCloser(float distance, state label, bool noz = false);

View file

@ -9,7 +9,7 @@ ACTOR Inventory native
action native state A_JumpIfNoAmmo(state label);
action native A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus", sound MeleeSound = "", sound MissSound = "");
action native A_FireBullets(float/*angle*/ spread_xy, float/*angle*/ spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", int flags = 1, float range = 0);
action native A_FireBullets(float/*angle*/ spread_xy, float/*angle*/ spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", int flags = 1, float range = 0, class<Actor> missile = "", float Spawnheight = 32, float Spawnofs_xy = 0);
action native A_FireCustomMissile(class<Actor> missiletype, float angle = 0, bool useammo = true, float spawnofs_xy = 0, float spawnheight = 0, int flags = 0, float pitch = 0);
action native A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float/*angle*/ spread_xy = 0, float/*angle*/ spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0);
action native A_Light(int extralight);

View file

@ -1835,6 +1835,7 @@ ALTHUDMNU_SHOWAMMO = "Show ammo for";
ALTHUDMNU_SHOWTIME = "Show time";
ALTHUDMNU_TIMECOLOR = "Time color";
ALTHUDMNU_SHOWLAG = "Show network latency";
ALTHUDMNU_AMMOORDER = "Ammo display order";
ALTHUDMNU_AMMORED = "Red ammo display below %";
ALTHUDMNU_AMMOYELLOW = "Yellow ammo display below %";
ALTHUDMNU_HEALTHRED = "Red health display below";
@ -2210,6 +2211,8 @@ OPTVAL_SYSTEMSECONDS = "System, seconds";
OPTVAL_SYSTEM = "System";
OPTVAL_NETGAMESONLY = "Netgames only";
OPTVAL_ALWAYS = "Always";
OPTVAL_AMMOIMAGETEXT = "Image and Text";
OPTVAL_AMMOTEXTIMAGE = "Text and Image";
OPTVAL_SCRIPTSONLY = "Scripts Only";
OPTVAL_NEVER = "Never";
OPTVAL_ALL = "All";

View file

@ -833,6 +833,12 @@ OptionValue "AltHUDLag"
2, "$OPTVAL_ALWAYS"
}
OptionValue "AltHUDAmmoOrder"
{
0, "$OPTVAL_AMMOIMAGETEXT"
1, "$OPTVAL_AMMOTEXTIMAGE"
}
OptionMenu "AltHUDOptions"
{
Title "$ALTHUDMNU_TITLE"
@ -849,6 +855,7 @@ OptionMenu "AltHUDOptions"
Option "$ALTHUDMNU_SHOWTIME", "hud_showtime", "AltHUDTime"
Option "$ALTHUDMNU_TIMECOLOR", "hud_timecolor", "TextColors"
Option "$ALTHUDMNU_SHOWLAG", "hud_showlag", "AltHUDLag"
Option "$ALTHUDMNU_AMMOORDER", "hud_ammo_order", "AltHUDAmmoOrder"
Slider "$ALTHUDMNU_AMMORED", "hud_ammo_red", 0, 100, 1, 0
Slider "$ALTHUDMNU_AMMOYELLOW", "hud_ammo_yellow", 0, 100, 1, 0
Slider "$ALTHUDMNU_HEALTHRED", "hud_health_red", 0, 100, 1, 0