diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 18af85a06..c936c303f 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,7 +1,17 @@ +March 7, 2007 +- Changed P_SpawnPlayerMissile() to use the same height calculation as + P_(Aim)LineAttack(). +- Added an AttackZOffset to PlayerPawn. This is the offset from the + center of the player at which their attacks are fired and scales + according to their crouched height. +- Changed the version of P_SpawnPlayerMissile() that takes coordinates + to use that location as an offset from the standard attack location + rather than as an explicit attack location. + March 6, 2007 - Added an IF_KEEPDEPLETED flag for inventory items to keep them in the player's inventory even when they have been used up. If the item also - has an inventory bar icon, it will be drawn darkened when it is + has an inventory bar icon, it will be drawn darkened while it is depleted. March 5, 2007 diff --git a/src/d_player.h b/src/d_player.h index 4ac2d16ba..04db087e5 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -116,6 +116,7 @@ public: int ScoreIcon; int SpawnMask; FNameNoInit MorphWeapon; + fixed_t AttackZOffset; // attack height, relative to player center bool UpdateWaterLevel (fixed_t oldz, bool splash); bool ResetAirSupply (); diff --git a/src/g_hexen/a_fighterquietus.cpp b/src/g_hexen/a_fighterquietus.cpp index c5b8a4ae4..12928be9d 100644 --- a/src/g_hexen/a_fighterquietus.cpp +++ b/src/g_hexen/a_fighterquietus.cpp @@ -305,11 +305,11 @@ void A_FSwordAttack (AActor *actor) if (!weapon->DepleteAmmo (weapon->bAltFire)) return; } - P_SpawnPlayerMissile (actor, actor->x, actor->y, actor->z-10*FRACUNIT, RUNTIME_CLASS(AFSwordMissile), actor->angle+ANGLE_45/4); - P_SpawnPlayerMissile (actor, actor->x, actor->y, actor->z-5*FRACUNIT, RUNTIME_CLASS(AFSwordMissile), actor->angle+ANGLE_45/8); - P_SpawnPlayerMissile (actor, actor->x, actor->y, actor->z, RUNTIME_CLASS(AFSwordMissile), actor->angle); - P_SpawnPlayerMissile (actor, actor->x, actor->y, actor->z+5*FRACUNIT, RUNTIME_CLASS(AFSwordMissile), actor->angle-ANGLE_45/8); - P_SpawnPlayerMissile (actor, actor->x, actor->y, actor->z+10*FRACUNIT, RUNTIME_CLASS(AFSwordMissile), actor->angle-ANGLE_45/4); + P_SpawnPlayerMissile (actor, 0, 0, -10*FRACUNIT, RUNTIME_CLASS(AFSwordMissile), actor->angle+ANGLE_45/4); + P_SpawnPlayerMissile (actor, 0, 0, -5*FRACUNIT, RUNTIME_CLASS(AFSwordMissile), actor->angle+ANGLE_45/8); + P_SpawnPlayerMissile (actor, 0, 0, 0, RUNTIME_CLASS(AFSwordMissile), actor->angle); + P_SpawnPlayerMissile (actor, 0, 0, 5*FRACUNIT, RUNTIME_CLASS(AFSwordMissile), actor->angle-ANGLE_45/8); + P_SpawnPlayerMissile (actor, 0, 0, 10*FRACUNIT, RUNTIME_CLASS(AFSwordMissile), actor->angle-ANGLE_45/4); S_Sound (actor, CHAN_WEAPON, "FighterSwordFire", 1, ATTN_NORM); } diff --git a/src/g_hexen/a_magestaff.cpp b/src/g_hexen/a_magestaff.cpp index 2d12c78d1..0c97c4e27 100644 --- a/src/g_hexen/a_magestaff.cpp +++ b/src/g_hexen/a_magestaff.cpp @@ -387,7 +387,7 @@ void MStaffSpawn (AActor *pmo, angle_t angle) { AActor *mo; - mo = P_SpawnPlayerMissile (pmo, pmo->x, pmo->y, pmo->z+8*FRACUNIT, + mo = P_SpawnPlayerMissile (pmo, 0, 0, 8*FRACUNIT, RUNTIME_CLASS(AMageStaffFX2), angle); if (mo) { diff --git a/src/info.h b/src/info.h index db3226cec..0956ba1f6 100644 --- a/src/info.h +++ b/src/info.h @@ -2,7 +2,7 @@ ** info.h ** **--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit +** Copyright 1998-2007 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -361,6 +361,7 @@ enum ADEF_PlayerPawn_SideMove2, ADEF_PlayerPawn_ColorRange, ADEF_PlayerPawn_SpawnMask, + ADEF_PlayerPawn_AttackZOffset, // The following are not properties but affect how the list is parsed ADEF_FirstCommand, diff --git a/src/infodefaults.cpp b/src/infodefaults.cpp index 2c418b96a..439ba813b 100644 --- a/src/infodefaults.cpp +++ b/src/infodefaults.cpp @@ -3,7 +3,7 @@ ** Parses default lists to create default copies of actors ** **--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit +** Copyright 1998-2007 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -310,6 +310,7 @@ static void ApplyActorDefault (int defnum, const char *datastr, int dataint) // [GRB] Player class properties case ADEF_PlayerPawn_JumpZ: player->JumpZ = dataint; break; + case ADEF_PlayerPawn_AttackZOffset: player->AttackZOffset = dataint; break; case ADEF_PlayerPawn_ViewHeight: player->ViewHeight = dataint; break; case ADEF_PlayerPawn_ForwardMove1: player->ForwardMove1 = dataint; break; case ADEF_PlayerPawn_ForwardMove2: player->ForwardMove2 = dataint; break; diff --git a/src/infomacros.h b/src/infomacros.h index 1b02edc18..4f1afd1c3 100644 --- a/src/infomacros.h +++ b/src/infomacros.h @@ -2,7 +2,7 @@ ** infomacros.h ** **--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit +** Copyright 1998-2007 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -32,13 +32,13 @@ ** This file contains macros for building Actor defaults lists ** Defaults lists are byte-packed arrays of keys and values. ** -** For Visual C++, a simple byte array will do, with one -** restriction: Any strings must be at the end of the array. +** For Visual C++, a simple byte array will do, with one restriction: +** Any strings must be at the end of the array. ** -** For GCC, we need to get more complicated: Everything needs -** to be a separate variable. Fortunately, GCC byte-aligns -** char variables, so as long they appear in the right order -** (which they do in all version I tried), this will work. +** For GCC, an initializer function is created instead, since GCC doesn't +** let you combine integers and strings in the same character array, and +** there's no way to guarantee that consecutive variables will be +** consecutive in the generated code. */ #ifndef __INFOMACROS_H__ @@ -342,5 +342,6 @@ public: #define PROP_PlayerPawn_SideMove2(x) ADD_LONG_PROP(ADEF_PlayerPawn_SideMove2,x) #define PROP_PlayerPawn_ColorRange(x,y) ADD_LONG_PROP(ADEF_PlayerPawn_ColorRange,x|(y<<8)) #define PROP_PlayerPawn_SpawnMask(x) ADD_BYTE_PROP(ADEF_PlayerPawn_SpawnMask, x) +#define PROP_PlayerPawn_AttackZOffset(x) ADD_FIXD_PROP(ADEF_PlayerPawn_AttackZOffset, x) #endif //__INFOMACROS_H__ diff --git a/src/p_map.cpp b/src/p_map.cpp index e251d87c6..0433f92ff 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2667,7 +2667,15 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, fixed_t vr x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; - shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; + shootz = t1->z + (t1->height>>1) - t1->floorclip; + if (t1->player != NULL) + { + shootz += FixedMul (t1->player->mo->AttackZOffset, t1->player->crouchfactor); + } + else + { + shootz += 8*FRACUNIT; + } // can't shoot outside view angles if (vrange == 0) @@ -2776,7 +2784,15 @@ void P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, vy = FixedMul (finecosine[pitch], finesine[angle]); vz = -finesine[pitch]; - shootz = t1->z - t1->floorclip + (t1->height>>1) + 8*FRACUNIT; + shootz = t1->z - t1->floorclip + (t1->height>>1); + if (t1->player != NULL) + { + shootz += FixedMul (t1->player->mo->AttackZOffset, t1->player->crouchfactor); + } + else + { + shootz += 8*FRACUNIT; + } attackrange = distance; aimpitch = pitch; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a78c367a9..8b7ff60db 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4432,8 +4432,8 @@ AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, // [RH] // Hexen calculates the missile velocity based on the source's location. // Would it be more useful to base it on the actual position of the - // missile? I'll leave it like this for now. - // Answer. No, because this way, you can set up sets of parallel missiles. + // missile? + // Answer: No, because this way, you can set up sets of parallel missiles. FVector3 velocity(dest->x - source->x, dest->y - source->y, dest->z - source->z); // Floor and ceiling huggers should never have a vertical component to their velocity @@ -4441,7 +4441,7 @@ AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, { velocity.Z = 0; } - // [RH] Adjust the trajectory if the missile will go over the player's head. + // [RH] Adjust the trajectory if the missile will go over the target's head. else if (z - source->z >= dest->height) { velocity.Z += dest->height - z + source->z; @@ -4567,12 +4567,12 @@ AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z, AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type) { - return P_SpawnPlayerMissile (source, source->x, source->y, source->z, type, source->angle); + return P_SpawnPlayerMissile (source, 0, 0, 0, type, source->angle); } AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type, angle_t angle) { - return P_SpawnPlayerMissile (source, source->x, source->y, source->z, type, angle); + return P_SpawnPlayerMissile (source, 0, 0, 0, type, angle); } AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, @@ -4615,9 +4615,23 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, } if (z != ONFLOORZ && z != ONCEILINGZ) { - z += 4*8*FRACUNIT - source->floorclip + (source->player? source->player->crouchoffset : 0); + // Doom spawns missiles 4 units lower than hitscan attacks for players. + z += source->z + (source->height>>1) - source->floorclip; + if (source->player != NULL) // Considering this is for player missiles, it better not be NULL. + { + z += FixedMul (source->player->mo->AttackZOffset - 4*FRACUNIT, source->player->crouchfactor); + } + else + { + z += 4*FRACUNIT; + } + // Do not fire beneath the floor. + if (z < source->floorz) + { + z = source->floorz; + } } - MissileActor = Spawn (type, x, y, z, ALLOW_REPLACE); + MissileActor = Spawn (type, source->x + x, source->y + y, z, ALLOW_REPLACE); P_PlaySpawnSound(MissileActor, source); MissileActor->target = source; MissileActor->angle = an; diff --git a/src/p_user.cpp b/src/p_user.cpp index fe2e54d8a..4eb3c6e4e 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -377,6 +377,7 @@ BEGIN_STATELESS_DEFAULTS (APlayerPawn, Any, -1, 0) PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY) PROP_Flags2 (MF2_SLIDE|MF2_PASSMOBJ|MF2_PUSHWALL|MF2_FLOORCLIP|MF2_WINDTHRUST|MF2_TELESTOMP) PROP_Flags3 (MF3_NOBLOCKMONST) + PROP_PlayerPawn_AttackZOffset (8) // [GRB] PROP_PlayerPawn_JumpZ (8*FRACUNIT) PROP_PlayerPawn_ViewHeight (41*FRACUNIT) diff --git a/src/thingdef.cpp b/src/thingdef.cpp index 862a5b0bc..96121ead2 100644 --- a/src/thingdef.cpp +++ b/src/thingdef.cpp @@ -3853,6 +3853,15 @@ static void PlayerColorRange (APlayerPawn *defaults, Baggage &bag) bag.Info->Class->Meta.SetMetaInt (APMETA_ColorRange, (start & 255) | ((end & 255) << 8)); } +//========================================================================== +// +//========================================================================== +static void PlayerAttackZOffset (APlayerPawn *defaults, Baggage &bag) +{ + SC_MustGetFloat (); + defaults->AttackZOffset = FLOAT2FIXED (sc_Float); +} + //========================================================================== // //========================================================================== @@ -4157,6 +4166,7 @@ static const ActorProps props[] = { "pain", ActorPainState, RUNTIME_CLASS(AActor) }, { "painchance", ActorPainChance, RUNTIME_CLASS(AActor) }, { "painsound", ActorPainSound, RUNTIME_CLASS(AActor) }, + { "player.attackzoffset", (apf)PlayerAttackZOffset, RUNTIME_CLASS(APlayerPawn) }, { "player.colorrange", (apf)PlayerColorRange, RUNTIME_CLASS(APlayerPawn) }, { "player.crouchsprite", (apf)PlayerCrouchSprite, RUNTIME_CLASS(APlayerPawn) }, { "player.displayname", (apf)PlayerDisplayName, RUNTIME_CLASS(APlayerPawn) }, diff --git a/src/thingdef_codeptr.cpp b/src/thingdef_codeptr.cpp index bf598f8b7..8fc3d0100 100644 --- a/src/thingdef_codeptr.cpp +++ b/src/thingdef_codeptr.cpp @@ -1043,7 +1043,7 @@ void A_FireCustomMissile (AActor * self) if (AimAtAngle) shootangle+=Angle; - AActor * misl=P_SpawnPlayerMissile (self, self->x+x, self->y+y, self->z+z, ti, shootangle); + AActor * misl=P_SpawnPlayerMissile (self, x, y, z, ti, shootangle); // automatic handling of seeker missiles if (misl) {