mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 07:12:16 +00:00
- scriptified the pistol to test if struct member functions work.
- made APlayerPawn::PlayAttacking(2) virtual script functions so that mods have better control over player animations. Note that these have no native base so they skip the templated interface for managing virtual functions.
This commit is contained in:
parent
de8cacc465
commit
d50da34664
15 changed files with 214 additions and 126 deletions
|
@ -2535,7 +2535,7 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray<DWORD> &argflags, TArra
|
||||||
assert(proto->ArgumentTypes.Size() > 0);
|
assert(proto->ArgumentTypes.Size() > 0);
|
||||||
auto selftypeptr = dyn_cast<PPointer>(proto->ArgumentTypes[0]);
|
auto selftypeptr = dyn_cast<PPointer>(proto->ArgumentTypes[0]);
|
||||||
assert(selftypeptr != nullptr);
|
assert(selftypeptr != nullptr);
|
||||||
variant.SelfClass = dyn_cast<PClass>(selftypeptr->PointedType);
|
variant.SelfClass = dyn_cast<PStruct>(selftypeptr->PointedType);
|
||||||
assert(variant.SelfClass != nullptr);
|
assert(variant.SelfClass != nullptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -22,40 +22,6 @@ static FRandom pr_firerail ("FireRail");
|
||||||
static FRandom pr_bfgspray ("BFGSpray");
|
static FRandom pr_bfgspray ("BFGSpray");
|
||||||
static FRandom pr_oldbfg ("OldBFG");
|
static FRandom pr_oldbfg ("OldBFG");
|
||||||
|
|
||||||
//
|
|
||||||
// A_FirePistol
|
|
||||||
//
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_FirePistol)
|
|
||||||
{
|
|
||||||
PARAM_ACTION_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
bool accurate;
|
|
||||||
|
|
||||||
if (self->player != nullptr)
|
|
||||||
{
|
|
||||||
AWeapon *weapon = self->player->ReadyWeapon;
|
|
||||||
if (weapon != nullptr && ACTION_CALL_FROM_PSPRITE())
|
|
||||||
{
|
|
||||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
P_SetPsprite(self->player, PSP_FLASH, weapon->FindState(NAME_Flash), true);
|
|
||||||
}
|
|
||||||
self->player->mo->PlayAttacking2 ();
|
|
||||||
|
|
||||||
accurate = !self->player->refire;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
accurate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
S_Sound (self, CHAN_WEAPON, "weapons/pistol", 1, ATTN_NORM);
|
|
||||||
|
|
||||||
P_GunShot (self, accurate, PClass::FindActor(NAME_BulletPuff), P_BulletSlope (self));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// A_Saw
|
// A_Saw
|
||||||
//
|
//
|
||||||
|
@ -71,6 +37,29 @@ enum SAW_Flags
|
||||||
SF_STEALARMOR = 128,
|
SF_STEALARMOR = 128,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static FRandom pr_gunshot("GunShot");
|
||||||
|
//
|
||||||
|
// P_GunShot
|
||||||
|
//
|
||||||
|
void P_GunShot(AActor *mo, bool accurate, PClassActor *pufftype, DAngle pitch)
|
||||||
|
{
|
||||||
|
DAngle angle;
|
||||||
|
int damage;
|
||||||
|
|
||||||
|
damage = 5 * (pr_gunshot() % 3 + 1);
|
||||||
|
angle = mo->Angles.Yaw;
|
||||||
|
|
||||||
|
if (!accurate)
|
||||||
|
{
|
||||||
|
angle += pr_gunshot.Random2() * (5.625 / 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
P_LineAttack(mo, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, pufftype);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_Saw)
|
DEFINE_ACTION_FUNCTION(AActor, A_Saw)
|
||||||
{
|
{
|
||||||
PARAM_ACTION_PROLOGUE(AActor);
|
PARAM_ACTION_PROLOGUE(AActor);
|
||||||
|
|
|
@ -79,7 +79,6 @@ CVAR(Int, sv_fastweapons, false, CVAR_SERVERINFO);
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
static FRandom pr_wpnreadysnd ("WpnReadySnd");
|
static FRandom pr_wpnreadysnd ("WpnReadySnd");
|
||||||
static FRandom pr_gunshot ("GunShot");
|
|
||||||
|
|
||||||
static const FGenericButtons ButtonChecks[] =
|
static const FGenericButtons ButtonChecks[] =
|
||||||
{
|
{
|
||||||
|
@ -184,6 +183,16 @@ void P_SetPsprite(player_t *player, PSPLayers id, FState *state, bool pending)
|
||||||
player->GetPSprite(id)->SetState(state, pending);
|
player->GetPSprite(id)->SetState(state, pending);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_Player, SetPSprite) // the underscore is needed to get past the name mangler which removes the first clas name character to match the class representation (needs to be fixed in a later commit)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||||
|
PARAM_INT(id);
|
||||||
|
PARAM_POINTER(state, FState);
|
||||||
|
PARAM_BOOL_DEF(pending);
|
||||||
|
P_SetPsprite(self, (PSPLayers)id, state, pending);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
DPSprite *player_t::GetPSprite(PSPLayers layer)
|
DPSprite *player_t::GetPSprite(PSPLayers layer)
|
||||||
{
|
{
|
||||||
AActor *oldcaller = nullptr;
|
AActor *oldcaller = nullptr;
|
||||||
|
@ -1381,6 +1390,15 @@ DAngle P_BulletSlope (AActor *mo, FTranslatedLineTarget *pLineTarget, int aimfla
|
||||||
return pitch;
|
return pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, BulletSlope)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
PARAM_POINTER_DEF(t, FTranslatedLineTarget);
|
||||||
|
PARAM_INT_DEF(aimflags);
|
||||||
|
ACTION_RETURN_FLOAT(P_BulletSlope(self, t, aimflags).Degrees);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
AActor *P_AimTarget(AActor *mo)
|
AActor *P_AimTarget(AActor *mo)
|
||||||
{
|
{
|
||||||
FTranslatedLineTarget t;
|
FTranslatedLineTarget t;
|
||||||
|
@ -1395,25 +1413,6 @@ DEFINE_ACTION_FUNCTION(AActor, AimTarget)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// P_GunShot
|
|
||||||
//
|
|
||||||
void P_GunShot (AActor *mo, bool accurate, PClassActor *pufftype, DAngle pitch)
|
|
||||||
{
|
|
||||||
DAngle angle;
|
|
||||||
int damage;
|
|
||||||
|
|
||||||
damage = 5*(pr_gunshot()%3+1);
|
|
||||||
angle = mo->Angles.Yaw;
|
|
||||||
|
|
||||||
if (!accurate)
|
|
||||||
{
|
|
||||||
angle += pr_gunshot.Random2 () * (5.625 / 256);
|
|
||||||
}
|
|
||||||
|
|
||||||
P_LineAttack (mo, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, pufftype);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_Light)
|
DEFINE_ACTION_FUNCTION(AActor, A_Light)
|
||||||
{
|
{
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
|
|
@ -111,8 +111,6 @@ void P_BobWeapon (player_t *player, float *x, float *y, double ticfrac);
|
||||||
DAngle P_BulletSlope (AActor *mo, FTranslatedLineTarget *pLineTarget = NULL, int aimflags = 0);
|
DAngle P_BulletSlope (AActor *mo, FTranslatedLineTarget *pLineTarget = NULL, int aimflags = 0);
|
||||||
AActor *P_AimTarget(AActor *mo);
|
AActor *P_AimTarget(AActor *mo);
|
||||||
|
|
||||||
void P_GunShot (AActor *mo, bool accurate, PClassActor *pufftype, DAngle pitch);
|
|
||||||
|
|
||||||
void DoReadyWeapon(AActor *self);
|
void DoReadyWeapon(AActor *self);
|
||||||
void DoReadyWeaponToBob(AActor *self);
|
void DoReadyWeaponToBob(AActor *self);
|
||||||
void DoReadyWeaponToFire(AActor *self, bool primary = true, bool secondary = true);
|
void DoReadyWeaponToFire(AActor *self, bool primary = true, bool secondary = true);
|
||||||
|
|
|
@ -1280,12 +1280,22 @@ void APlayerPawn::PlayRunning ()
|
||||||
|
|
||||||
void APlayerPawn::PlayAttacking ()
|
void APlayerPawn::PlayAttacking ()
|
||||||
{
|
{
|
||||||
if (MissileState != NULL) SetState (MissileState);
|
static int VIndex = -1;
|
||||||
|
if (VIndex < 0) VIndex = GetVirtualIndex(RUNTIME_CLASS(APlayerPawn), "PlayAttacking");
|
||||||
|
// Without the type cast this picks the 'void *' assignment...
|
||||||
|
VMValue params[1] = { (DObject*)this };
|
||||||
|
VMFrameStack stack;
|
||||||
|
stack.Call(this->GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APlayerPawn::PlayAttacking2 ()
|
void APlayerPawn::PlayAttacking2 ()
|
||||||
{
|
{
|
||||||
if (MeleeState != NULL) SetState (MeleeState);
|
static int VIndex = -1;
|
||||||
|
if (VIndex < 0) VIndex = GetVirtualIndex(RUNTIME_CLASS(APlayerPawn), "PlayAttacking2");
|
||||||
|
// Without the type cast this picks the 'void *' assignment...
|
||||||
|
VMValue params[1] = { (DObject*)this };
|
||||||
|
VMFrameStack stack;
|
||||||
|
stack.Call(this->GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APlayerPawn::ThrowPoisonBag ()
|
void APlayerPawn::ThrowPoisonBag ()
|
||||||
|
|
|
@ -6706,7 +6706,7 @@ FxMemberFunctionCall::~FxMemberFunctionCall()
|
||||||
FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
ABORT(ctx.Class);
|
ABORT(ctx.Class);
|
||||||
PClass *cls;
|
PStruct *cls;
|
||||||
bool staticonly = false;
|
bool staticonly = false;
|
||||||
bool novirtual = false;
|
bool novirtual = false;
|
||||||
|
|
||||||
|
@ -6714,13 +6714,21 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
// If the left side is a class name for a static member function call it needs to be resolved manually
|
// If the left side is a class name for a static member function call it needs to be resolved manually
|
||||||
// because the resulting value type would cause problems in nearly every other place where identifiers are being used.
|
// because the resulting value type would cause problems in nearly every other place where identifiers are being used.
|
||||||
cls = PClass::FindClass(static_cast<FxIdentifier *>(Self)->Identifier);
|
PClass *ccls = PClass::FindClass(static_cast<FxIdentifier *>(Self)->Identifier);
|
||||||
if (cls != nullptr && cls->bExported)
|
if (ccls != nullptr)
|
||||||
{
|
{
|
||||||
|
if (ccls->bExported)
|
||||||
|
{
|
||||||
|
cls = ccls;
|
||||||
staticonly = true;
|
staticonly = true;
|
||||||
goto isresolved;
|
goto isresolved;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Todo: static struct members need to work as well.
|
||||||
|
}
|
||||||
|
}
|
||||||
SAFE_RESOLVE(Self, ctx);
|
SAFE_RESOLVE(Self, ctx);
|
||||||
|
|
||||||
if (Self->ExprType == EFX_Super)
|
if (Self->ExprType == EFX_Super)
|
||||||
|
@ -6755,9 +6763,9 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||||
{
|
{
|
||||||
auto ptype = static_cast<PPointer *>(Self->ValueType)->PointedType;
|
auto ptype = static_cast<PPointer *>(Self->ValueType)->PointedType;
|
||||||
if (ptype->IsKindOf(RUNTIME_CLASS(PClass)))
|
if (ptype->IsKindOf(RUNTIME_CLASS(PStruct)))
|
||||||
{
|
{
|
||||||
cls = static_cast<PClass *>(ptype);
|
cls = static_cast<PStruct *>(ptype);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -6773,6 +6781,8 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Todo: handle member calls from instantiated structs.
|
||||||
|
|
||||||
isresolved:
|
isresolved:
|
||||||
bool error = false;
|
bool error = false;
|
||||||
PFunction *afd = FindClassMemberFunction(cls, ctx.Class, MethodName, ScriptPosition, &error);
|
PFunction *afd = FindClassMemberFunction(cls, ctx.Class, MethodName, ScriptPosition, &error);
|
||||||
|
@ -6792,7 +6802,8 @@ isresolved:
|
||||||
if (staticonly && (afd->Variants[0].Flags & VARF_Method))
|
if (staticonly && (afd->Variants[0].Flags & VARF_Method))
|
||||||
{
|
{
|
||||||
auto clstype = dyn_cast<PClass>(ctx.Class);
|
auto clstype = dyn_cast<PClass>(ctx.Class);
|
||||||
if (clstype == nullptr || !clstype->IsDescendantOf(cls))
|
auto ccls = dyn_cast<PClass>(cls);
|
||||||
|
if (clstype == nullptr || ccls == nullptr || !clstype->IsDescendantOf(ccls))
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Cannot call non-static function %s::%s from here\n", cls->TypeName.GetChars(), MethodName.GetChars());
|
ScriptPosition.Message(MSG_ERROR, "Cannot call non-static function %s::%s from here\n", cls->TypeName.GetChars(), MethodName.GetChars());
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -7067,7 +7078,7 @@ VMFunction *FxVMFunctionCall::GetDirectFunction()
|
||||||
if (ArgList.Size() == 0 && !(Function->Variants[0].Flags & VARF_Virtual))
|
if (ArgList.Size() == 0 && !(Function->Variants[0].Flags & VARF_Virtual))
|
||||||
{
|
{
|
||||||
unsigned imp = Function->GetImplicitArgs();
|
unsigned imp = Function->GetImplicitArgs();
|
||||||
if (Function->Variants[0].ArgFlags.Size() <= imp || !(Function->Variants[0].ArgFlags[imp] & VARF_Optional)) return nullptr;
|
if (Function->Variants[0].ArgFlags.Size() > imp && !(Function->Variants[0].ArgFlags[imp] & VARF_Optional)) return nullptr;
|
||||||
return Function->Variants[0].Implementation;
|
return Function->Variants[0].Implementation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1032,8 +1032,6 @@ struct AFuncDesc
|
||||||
// change every single use in case the parameters change.
|
// change every single use in case the parameters change.
|
||||||
#define DECLARE_ACTION(name) extern VMNativeFunction *AActor_##name##_VMPtr;
|
#define DECLARE_ACTION(name) extern VMNativeFunction *AActor_##name##_VMPtr;
|
||||||
|
|
||||||
// This distinction is here so that CALL_ACTION produces errors when trying to
|
|
||||||
// access a function that requires parameters.
|
|
||||||
#define DEFINE_ACTION_FUNCTION(cls, name) \
|
#define DEFINE_ACTION_FUNCTION(cls, name) \
|
||||||
static int AF_##cls##_##name(VM_ARGS); \
|
static int AF_##cls##_##name(VM_ARGS); \
|
||||||
VMNativeFunction *cls##_##name##_VMPtr; \
|
VMNativeFunction *cls##_##name##_VMPtr; \
|
||||||
|
@ -1077,6 +1075,10 @@ void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self);
|
||||||
PARAM_PROLOGUE; \
|
PARAM_PROLOGUE; \
|
||||||
PARAM_OBJECT(self, type);
|
PARAM_OBJECT(self, type);
|
||||||
|
|
||||||
|
// for structs we need to check for ATAG_GENERIC instead of ATAG_OBJECT
|
||||||
|
#define PARAM_SELF_STRUCT_PROLOGUE(type) \
|
||||||
|
PARAM_PROLOGUE; \
|
||||||
|
PARAM_POINTER(self, type);
|
||||||
|
|
||||||
class PFunction;
|
class PFunction;
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,17 @@ VMEXPORTED_NATIVES_START
|
||||||
VMEXPORTED_NATIVES_FUNC(PostBeginPlay)
|
VMEXPORTED_NATIVES_FUNC(PostBeginPlay)
|
||||||
VMEXPORTED_NATIVES_END
|
VMEXPORTED_NATIVES_END
|
||||||
|
|
||||||
|
|
||||||
|
inline int GetVirtualIndex(PClass *cls, const char *funcname)
|
||||||
|
{
|
||||||
|
// Look up the virtual function index in the defining class because this may have gotten overloaded in subclasses with something different than a virtual override.
|
||||||
|
auto sym = dyn_cast<PFunction>(cls->Symbols.FindSymbol(funcname, false));
|
||||||
|
assert(sym != nullptr);
|
||||||
|
auto VIndex = sym->Variants[0].Implementation->VirtualIndex;
|
||||||
|
assert(VIndex >= 0);
|
||||||
|
return VIndex;
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class DVMObject : public T
|
class DVMObject : public T
|
||||||
{
|
{
|
||||||
|
@ -79,14 +90,7 @@ public:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static int VIndex = -1;
|
static int VIndex = -1;
|
||||||
if (VIndex < 0)
|
if (VIndex < 0) VIndex = GetVirtualIndex(RUNTIME_CLASS(DObject), "Destroy");
|
||||||
{
|
|
||||||
// Look up the virtual function index in the defining class because this may have gotten overloaded in subclasses with something different than a virtual override.
|
|
||||||
auto sym = dyn_cast<PFunction>(RUNTIME_CLASS(DObject)->Symbols.FindSymbol("Destroy", false));
|
|
||||||
assert(sym != nullptr);
|
|
||||||
VIndex = sym->Variants[0].Implementation->VirtualIndex;
|
|
||||||
assert(VIndex >= 0);
|
|
||||||
}
|
|
||||||
// Without the type cast this picks the 'void *' assignment...
|
// Without the type cast this picks the 'void *' assignment...
|
||||||
VMValue params[1] = { (DObject*)this };
|
VMValue params[1] = { (DObject*)this };
|
||||||
VMFrameStack stack;
|
VMFrameStack stack;
|
||||||
|
|
|
@ -49,6 +49,7 @@ zscript/doom/spidermaster.txt
|
||||||
zscript/doom/keen.txt
|
zscript/doom/keen.txt
|
||||||
zscript/doom/bossbrain.txt
|
zscript/doom/bossbrain.txt
|
||||||
zscript/doom/weaponfist.txt
|
zscript/doom/weaponfist.txt
|
||||||
|
zscript/doom/weaponpistol.txt
|
||||||
|
|
||||||
zscript/doom/deadthings.txt
|
zscript/doom/deadthings.txt
|
||||||
zscript/doom/doomammo.txt
|
zscript/doom/doomammo.txt
|
||||||
|
|
|
@ -78,6 +78,7 @@ class Actor : Thinker native
|
||||||
native void SetXYZ(vector3 newpos);
|
native void SetXYZ(vector3 newpos);
|
||||||
native Actor GetPointer(int aaptr);
|
native Actor GetPointer(int aaptr);
|
||||||
native void FaceMovementDirection();
|
native void FaceMovementDirection();
|
||||||
|
native double BulletSlope(out FTranslatedLineTarget pLineTarget = null, int aimflags = 0);
|
||||||
native Actor AimTarget();
|
native Actor AimTarget();
|
||||||
native bool CheckMissileSpawn(double maxdist);
|
native bool CheckMissileSpawn(double maxdist);
|
||||||
native bool CheckPosition(Vector2 pos, bool actorsonly = false);
|
native bool CheckPosition(Vector2 pos, bool actorsonly = false);
|
||||||
|
|
|
@ -711,6 +711,7 @@ enum EPSpriteFlags
|
||||||
// Default psprite layers
|
// Default psprite layers
|
||||||
enum EPSPLayers
|
enum EPSPLayers
|
||||||
{
|
{
|
||||||
|
PSP_STRIFEHANDS = -1,
|
||||||
PSP_WEAPON = 1,
|
PSP_WEAPON = 1,
|
||||||
PSP_FLASH = 1000,
|
PSP_FLASH = 1000,
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,53 +13,6 @@ class DoomWeapon : Weapon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Pistol
|
|
||||||
//
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class Pistol : DoomWeapon
|
|
||||||
{
|
|
||||||
Default
|
|
||||||
{
|
|
||||||
Weapon.SelectionOrder 1900;
|
|
||||||
Weapon.AmmoUse 1;
|
|
||||||
Weapon.AmmoGive 20;
|
|
||||||
Weapon.AmmoType "Clip";
|
|
||||||
Obituary "$OB_MPPISTOL";
|
|
||||||
+WEAPON.WIMPY_WEAPON
|
|
||||||
Inventory.Pickupmessage "$PICKUP_PISTOL_DROPPED";
|
|
||||||
Tag "$TAG_PISTOL";
|
|
||||||
}
|
|
||||||
States
|
|
||||||
{
|
|
||||||
Ready:
|
|
||||||
PISG A 1 A_WeaponReady;
|
|
||||||
Loop;
|
|
||||||
Deselect:
|
|
||||||
PISG A 1 A_Lower;
|
|
||||||
Loop;
|
|
||||||
Select:
|
|
||||||
PISG A 1 A_Raise;
|
|
||||||
Loop;
|
|
||||||
Fire:
|
|
||||||
PISG A 4;
|
|
||||||
PISG B 6 A_FirePistol;
|
|
||||||
PISG C 4;
|
|
||||||
PISG B 5 A_ReFire;
|
|
||||||
Goto Ready;
|
|
||||||
Flash:
|
|
||||||
PISF A 7 Bright A_Light1;
|
|
||||||
Goto LightDone;
|
|
||||||
PISF A 7 Bright A_Light1;
|
|
||||||
Goto LightDone;
|
|
||||||
Spawn:
|
|
||||||
PIST A -1;
|
|
||||||
Stop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Chainsaw
|
// Chainsaw
|
||||||
|
|
100
wadsrc/static/zscript/doom/weaponpistol.txt
Normal file
100
wadsrc/static/zscript/doom/weaponpistol.txt
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Pistol
|
||||||
|
//
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class Pistol : DoomWeapon
|
||||||
|
{
|
||||||
|
Default
|
||||||
|
{
|
||||||
|
Weapon.SelectionOrder 1900;
|
||||||
|
Weapon.AmmoUse 1;
|
||||||
|
Weapon.AmmoGive 20;
|
||||||
|
Weapon.AmmoType "Clip";
|
||||||
|
Obituary "$OB_MPPISTOL";
|
||||||
|
+WEAPON.WIMPY_WEAPON
|
||||||
|
Inventory.Pickupmessage "$PICKUP_PISTOL_DROPPED";
|
||||||
|
Tag "$TAG_PISTOL";
|
||||||
|
}
|
||||||
|
States
|
||||||
|
{
|
||||||
|
Ready:
|
||||||
|
PISG A 1 A_WeaponReady;
|
||||||
|
Loop;
|
||||||
|
Deselect:
|
||||||
|
PISG A 1 A_Lower;
|
||||||
|
Loop;
|
||||||
|
Select:
|
||||||
|
PISG A 1 A_Raise;
|
||||||
|
Loop;
|
||||||
|
Fire:
|
||||||
|
PISG A 4;
|
||||||
|
PISG B 6 A_FirePistol;
|
||||||
|
PISG C 4;
|
||||||
|
PISG B 5 A_ReFire;
|
||||||
|
Goto Ready;
|
||||||
|
Flash:
|
||||||
|
PISF A 7 Bright A_Light1;
|
||||||
|
Goto LightDone;
|
||||||
|
PISF A 7 Bright A_Light1;
|
||||||
|
Goto LightDone;
|
||||||
|
Spawn:
|
||||||
|
PIST A -1;
|
||||||
|
Stop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Code (must be attached to StateProvider)
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
extend class StateProvider
|
||||||
|
{
|
||||||
|
//===========================================================================
|
||||||
|
// This is also used by the shotgun and chaingun
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
protected action void GunShot(bool accurate, Class<Actor> pufftype, double pitch)
|
||||||
|
{
|
||||||
|
int damage = 5 * random[GunShot](1, 3);
|
||||||
|
double ang = angle;
|
||||||
|
|
||||||
|
if (!accurate)
|
||||||
|
{
|
||||||
|
ang += Random2[GunShot]() * (5.625 / 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
LineAttack(ang, PLAYERMISSILERANGE, pitch, damage, 'Hitscan', pufftype);
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
action void A_FirePistol()
|
||||||
|
{
|
||||||
|
bool accurate;
|
||||||
|
|
||||||
|
if (player != null)
|
||||||
|
{
|
||||||
|
Weapon weap = player.ReadyWeapon;
|
||||||
|
if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite)
|
||||||
|
{
|
||||||
|
if (!weap.DepleteAmmo (weap.bAltFire, true, 1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
player.SetPsprite(PSP_FLASH, weap.FindState('Flash'), true);
|
||||||
|
}
|
||||||
|
player.mo.PlayAttacking2 ();
|
||||||
|
|
||||||
|
accurate = !player.refire;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
accurate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
A_PlaySound ("weapons/pistol", CHAN_WEAPON);
|
||||||
|
GunShot (accurate, "BulletPuff", BulletSlope ());
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,7 +49,6 @@ class StateProvider : Inventory native
|
||||||
action native void A_WeaponReady(int flags = 0);
|
action native void A_WeaponReady(int flags = 0);
|
||||||
action native void A_Lower();
|
action native void A_Lower();
|
||||||
action native void A_Raise();
|
action native void A_Raise();
|
||||||
action native void A_FirePistol();
|
|
||||||
action native void A_FireShotgun();
|
action native void A_FireShotgun();
|
||||||
action native void A_FireShotgun2();
|
action native void A_FireShotgun2();
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,17 @@ class PlayerPawn : Actor native
|
||||||
Player.ViewBob 1;
|
Player.ViewBob 1;
|
||||||
Obituary "$OB_MPDEFAULT";
|
Obituary "$OB_MPDEFAULT";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void PlayAttacking ()
|
||||||
|
{
|
||||||
|
if (MissileState != null) SetState (MissileState);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void PlayAttacking2 ()
|
||||||
|
{
|
||||||
|
if (MeleeState != null) SetState (MeleeState);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class PlayerChunk : PlayerPawn native
|
class PlayerChunk : PlayerPawn native
|
||||||
|
@ -57,3 +68,12 @@ class PlayerChunk : PlayerPawn native
|
||||||
-TELESTOMP
|
-TELESTOMP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PSprite : Object native
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Player native
|
||||||
|
{
|
||||||
|
native void SetPsprite(int id, State stat, bool pending = false);
|
||||||
|
}
|
Loading…
Reference in a new issue