mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-02-17 17:41:23 +00:00
- implemented pass-by-reference arguments - so far only for memory based variables.
- changed Dehacked weapon function lookup to check the symbol table instead of directly referencing the VM functions. Once scriptified these pointers will no longer be available. - removed all special ATAGs from the VM. While well intentioned any pointer tagged with them is basically unusable because it'd trigger asserts all over the place. - scriptified A_Punch for testing pass-by-reference parameters and stack variables.
This commit is contained in:
parent
7ff5069617
commit
3ce699bf9b
20 changed files with 205 additions and 126 deletions
|
@ -166,36 +166,27 @@ static TArray<CodePointerAlias> MBFCodePointers;
|
||||||
|
|
||||||
struct AmmoPerAttack
|
struct AmmoPerAttack
|
||||||
{
|
{
|
||||||
VMNativeFunction **func;
|
ENamedName func;
|
||||||
int ammocount;
|
int ammocount;
|
||||||
|
VMFunction *ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_ACTION(A_Punch)
|
DECLARE_ACTION(A_Punch)
|
||||||
DECLARE_ACTION(A_FirePistol)
|
|
||||||
DECLARE_ACTION(A_FireShotgun)
|
|
||||||
DECLARE_ACTION(A_FireShotgun2)
|
|
||||||
DECLARE_ACTION(A_FireCGun)
|
|
||||||
DECLARE_ACTION(A_FireMissile)
|
|
||||||
DECLARE_ACTION(A_Saw)
|
|
||||||
DECLARE_ACTION(A_FirePlasma)
|
|
||||||
DECLARE_ACTION(A_FireBFG)
|
|
||||||
DECLARE_ACTION(A_FireOldBFG)
|
|
||||||
DECLARE_ACTION(A_FireRailgun)
|
|
||||||
|
|
||||||
// Default ammo use of the various weapon attacks
|
// Default ammo use of the various weapon attacks
|
||||||
static AmmoPerAttack AmmoPerAttacks[] = {
|
static AmmoPerAttack AmmoPerAttacks[] = {
|
||||||
{ &AActor_A_Punch_VMPtr, 0},
|
{ NAME_A_Punch, 0},
|
||||||
{ &AActor_A_FirePistol_VMPtr, 1},
|
{ NAME_A_FirePistol, 1},
|
||||||
{ &AActor_A_FireShotgun_VMPtr, 1},
|
{ NAME_A_FireShotgun, 1},
|
||||||
{ &AActor_A_FireShotgun2_VMPtr, 2},
|
{ NAME_A_FireShotgun2, 2},
|
||||||
{ &AActor_A_FireCGun_VMPtr, 1},
|
{ NAME_A_FireCGun, 1},
|
||||||
{ &AActor_A_FireMissile_VMPtr, 1},
|
{ NAME_A_FireMissile, 1},
|
||||||
{ &AActor_A_Saw_VMPtr, 0},
|
{ NAME_A_Saw, 0},
|
||||||
{ &AActor_A_FirePlasma_VMPtr, 1},
|
{ NAME_A_FirePlasma, 1},
|
||||||
{ &AActor_A_FireBFG_VMPtr, -1}, // uses deh.BFGCells
|
{ NAME_A_FireBFG, -1}, // uses deh.BFGCells
|
||||||
{ &AActor_A_FireOldBFG_VMPtr, 1},
|
{ NAME_A_FireOldBFG, 1},
|
||||||
{ &AActor_A_FireRailgun_VMPtr, 1},
|
{ NAME_A_FireRailgun, 1},
|
||||||
{ NULL, 0}
|
{ NAME_None, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -3095,7 +3086,12 @@ void FinishDehPatch ()
|
||||||
StateVisited[state] = true;
|
StateVisited[state] = true;
|
||||||
for(unsigned j = 0; AmmoPerAttacks[j].func != NULL; j++)
|
for(unsigned j = 0; AmmoPerAttacks[j].func != NULL; j++)
|
||||||
{
|
{
|
||||||
if (state->ActionFunc == *AmmoPerAttacks[j].func)
|
if (AmmoPerAttacks[i].ptr == nullptr)
|
||||||
|
{
|
||||||
|
auto p = dyn_cast<PFunction>(RUNTIME_CLASS(AStateProvider)->Symbols.FindSymbol(AmmoPerAttacks[i].func, true));
|
||||||
|
if (p != nullptr) AmmoPerAttacks[i].ptr = p->Variants[0].Implementation;
|
||||||
|
}
|
||||||
|
if (state->ActionFunc == AmmoPerAttacks[j].ptr)
|
||||||
{
|
{
|
||||||
found = true;
|
found = true;
|
||||||
int use = AmmoPerAttacks[j].ammocount;
|
int use = AmmoPerAttacks[j].ammocount;
|
||||||
|
|
|
@ -253,11 +253,10 @@ enum
|
||||||
WF_USER4OK = 1 << 11,
|
WF_USER4OK = 1 << 11,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define WPIECE1 1
|
// The VM cannot deal with this as an invalid pointer because it performs a read barrier on every object pointer read.
|
||||||
#define WPIECE2 2
|
// This doesn't have to point to a valid weapon, though, because WP_NOCHANGE is never dereferenced, but it must point to a valid object
|
||||||
#define WPIECE3 4
|
// and the class descriptor just works fine for that.
|
||||||
|
#define WP_NOCHANGE ((AWeapon*)RUNTIME_CLASS_CASTLESS(AWeapon))
|
||||||
#define WP_NOCHANGE ((AWeapon*)~0)
|
|
||||||
|
|
||||||
|
|
||||||
#define MAXPLAYERNAME 15
|
#define MAXPLAYERNAME 15
|
||||||
|
|
|
@ -32,6 +32,7 @@ enum
|
||||||
VARF_Static = (1<<13), // static class data (by necessity read only.)
|
VARF_Static = (1<<13), // static class data (by necessity read only.)
|
||||||
VARF_InternalAccess = (1<<14), // overrides VARF_ReadOnly for internal script code.
|
VARF_InternalAccess = (1<<14), // overrides VARF_ReadOnly for internal script code.
|
||||||
VARF_Override = (1<<15), // overrides a virtual function from the parent class.
|
VARF_Override = (1<<15), // overrides a virtual function from the parent class.
|
||||||
|
VARF_Ref = (1<<16), // argument is passed by reference.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Symbol information -------------------------------------------------------
|
// Symbol information -------------------------------------------------------
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "doomstat.h"
|
#include "doomstat.h"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static FRandom pr_punch ("Punch");
|
|
||||||
static FRandom pr_saw ("Saw");
|
static FRandom pr_saw ("Saw");
|
||||||
static FRandom pr_fireshotgun2 ("FireSG2");
|
static FRandom pr_fireshotgun2 ("FireSG2");
|
||||||
static FRandom pr_fireplasma ("FirePlasma");
|
static FRandom pr_fireplasma ("FirePlasma");
|
||||||
|
@ -23,47 +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_Punch
|
|
||||||
//
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_Punch)
|
|
||||||
{
|
|
||||||
PARAM_ACTION_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
DAngle angle;
|
|
||||||
int damage;
|
|
||||||
DAngle pitch;
|
|
||||||
FTranslatedLineTarget t;
|
|
||||||
|
|
||||||
if (self->player != NULL)
|
|
||||||
{
|
|
||||||
AWeapon *weapon = self->player->ReadyWeapon;
|
|
||||||
if (weapon != NULL && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_PSPRITE())
|
|
||||||
{
|
|
||||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
damage = (pr_punch()%10+1)<<1;
|
|
||||||
|
|
||||||
if (self->FindInventory<APowerStrength>())
|
|
||||||
damage *= 10;
|
|
||||||
|
|
||||||
angle = self->Angles.Yaw + pr_punch.Random2() * (5.625 / 256);
|
|
||||||
pitch = P_AimLineAttack (self, angle, MELEERANGE);
|
|
||||||
|
|
||||||
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, LAF_ISMELEEATTACK, &t);
|
|
||||||
|
|
||||||
// turn to face target
|
|
||||||
if (t.linetarget)
|
|
||||||
{
|
|
||||||
S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM);
|
|
||||||
self->Angles.Yaw = t.angleFromSource;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// A_FirePistol
|
// A_FirePistol
|
||||||
//
|
//
|
||||||
|
|
|
@ -289,6 +289,7 @@ public:
|
||||||
class AWeapon : public AStateProvider
|
class AWeapon : public AStateProvider
|
||||||
{
|
{
|
||||||
DECLARE_CLASS_WITH_META(AWeapon, AStateProvider, PClassWeapon)
|
DECLARE_CLASS_WITH_META(AWeapon, AStateProvider, PClassWeapon)
|
||||||
|
HAS_FIELDS
|
||||||
HAS_OBJECT_POINTERS
|
HAS_OBJECT_POINTERS
|
||||||
public:
|
public:
|
||||||
DWORD WeaponFlags;
|
DWORD WeaponFlags;
|
||||||
|
|
|
@ -17,10 +17,13 @@
|
||||||
#include "g_level.h"
|
#include "g_level.h"
|
||||||
#include "d_net.h"
|
#include "d_net.h"
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
|
#include "thingdef.h"
|
||||||
|
|
||||||
#define BONUSADD 6
|
#define BONUSADD 6
|
||||||
|
|
||||||
IMPLEMENT_CLASS(AWeapon, false, true, false, false)
|
extern FFlagDef WeaponFlagDefs[];
|
||||||
|
|
||||||
|
IMPLEMENT_CLASS(AWeapon, false, true, true, false)
|
||||||
|
|
||||||
IMPLEMENT_POINTERS_START(AWeapon)
|
IMPLEMENT_POINTERS_START(AWeapon)
|
||||||
IMPLEMENT_POINTER(Ammo1)
|
IMPLEMENT_POINTER(Ammo1)
|
||||||
|
@ -28,6 +31,26 @@ IMPLEMENT_POINTERS_START(AWeapon)
|
||||||
IMPLEMENT_POINTER(SisterWeapon)
|
IMPLEMENT_POINTER(SisterWeapon)
|
||||||
IMPLEMENT_POINTERS_END
|
IMPLEMENT_POINTERS_END
|
||||||
|
|
||||||
|
void AWeapon::InitNativeFields()
|
||||||
|
{
|
||||||
|
auto meta = RUNTIME_CLASS(AWeapon);
|
||||||
|
|
||||||
|
meta->AddNativeField("bAltFire", TypeBool, myoffsetof(AWeapon, bAltFire));
|
||||||
|
|
||||||
|
|
||||||
|
// synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them.
|
||||||
|
for (size_t i = 0; WeaponFlagDefs[i].flagbit != 0xffffffff; i++)
|
||||||
|
{
|
||||||
|
if (WeaponFlagDefs[i].structoffset > 0)
|
||||||
|
{
|
||||||
|
meta->AddNativeField(FStringf("b%s", WeaponFlagDefs[i].name), (WeaponFlagDefs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), WeaponFlagDefs[i].structoffset, WeaponFlagDefs[i].varflags, WeaponFlagDefs[i].flagbit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// This flag is not accessible through actor definitions.
|
||||||
|
meta->AddNativeField("bDehAmmo", TypeSInt32, myoffsetof(AWeapon, WeaponFlags), VARF_ReadOnly, WIF_DEHAMMO);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
FString WeaponSection;
|
FString WeaponSection;
|
||||||
TArray<FString> KeyConfWeapons;
|
TArray<FString> KeyConfWeapons;
|
||||||
FWeaponSlots *PlayingKeyConf;
|
FWeaponSlots *PlayingKeyConf;
|
||||||
|
@ -651,6 +674,15 @@ bool AWeapon::DepleteAmmo (bool altFire, bool checkEnough, int ammouse)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AWeapon, DepleteAmmo)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AWeapon);
|
||||||
|
PARAM_BOOL(altfire);
|
||||||
|
PARAM_BOOL_DEF(checkenough);
|
||||||
|
PARAM_INT_DEF(ammouse);
|
||||||
|
ACTION_RETURN_BOOL(self->DepleteAmmo(altfire, checkenough, ammouse));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -738,3 +738,15 @@ xx(Length)
|
||||||
xx(Unit)
|
xx(Unit)
|
||||||
xx(StateLabel)
|
xx(StateLabel)
|
||||||
xx(Overlay)
|
xx(Overlay)
|
||||||
|
|
||||||
|
xx(A_Punch)
|
||||||
|
xx(A_FirePistol)
|
||||||
|
xx(A_FireShotgun)
|
||||||
|
xx(A_FireShotgun2)
|
||||||
|
xx(A_FireCGun)
|
||||||
|
xx(A_FireMissile)
|
||||||
|
xx(A_Saw)
|
||||||
|
xx(A_FirePlasma)
|
||||||
|
xx(A_FireBFG)
|
||||||
|
xx(A_FireOldBFG)
|
||||||
|
xx(A_FireRailgun)
|
||||||
|
|
|
@ -1035,6 +1035,14 @@ AInventory *AActor::FindInventory (FName type)
|
||||||
return FindInventory(PClass::FindActor(type));
|
return FindInventory(PClass::FindActor(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, FindInventory)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
PARAM_CLASS(type, AInventory);
|
||||||
|
PARAM_BOOL_DEF(subclass);
|
||||||
|
ACTION_RETURN_OBJECT(self->FindInventory(type, subclass));
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// AActor :: GiveInventoryType
|
// AActor :: GiveInventoryType
|
||||||
|
|
|
@ -3547,7 +3547,7 @@ ExpEmit FxShift::Emit(VMFunctionBuilder *build)
|
||||||
if (!op1.Konst)
|
if (!op1.Konst)
|
||||||
{
|
{
|
||||||
op1.Free(build);
|
op1.Free(build);
|
||||||
instr = InstrMap[index][op2.Konst? 0:2];
|
instr = InstrMap[index][op2.Konst? 2:0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -7067,7 +7067,8 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
SAFE_RESOLVE_OPT(Self, ctx);
|
SAFE_RESOLVE_OPT(Self, ctx);
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
auto proto = Function->Variants[0].Proto;
|
auto proto = Function->Variants[0].Proto;
|
||||||
auto argtypes = proto->ArgumentTypes;
|
auto &argtypes = proto->ArgumentTypes;
|
||||||
|
auto &argflags = Function->Variants[0].ArgFlags;
|
||||||
|
|
||||||
int implicit = Function->GetImplicitArgs();
|
int implicit = Function->GetImplicitArgs();
|
||||||
|
|
||||||
|
@ -7100,8 +7101,29 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
assert(type != nullptr);
|
assert(type != nullptr);
|
||||||
|
|
||||||
FxExpression *x = new FxTypeCast(ArgList[i], type, false);
|
FxExpression *x;
|
||||||
x = x->Resolve(ctx);
|
if (!(argflags[i + implicit] & VARF_Ref))
|
||||||
|
{
|
||||||
|
x = new FxTypeCast(ArgList[i], type, false);
|
||||||
|
x = x->Resolve(ctx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool writable;
|
||||||
|
ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested.
|
||||||
|
ArgList[i]->RequestAddress(ctx, &writable);
|
||||||
|
ArgList[i]->ValueType = NewPointer(ArgList[i]->ValueType);
|
||||||
|
// For a reference argument the types must match 100%.
|
||||||
|
if (type != ArgList[i]->ValueType)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in reference argument", Function->SymbolName.GetChars());
|
||||||
|
x = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = ArgList[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
failed |= (x == nullptr);
|
failed |= (x == nullptr);
|
||||||
ArgList[i] = x;
|
ArgList[i] = x;
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,7 +131,7 @@ void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FNam
|
||||||
{
|
{
|
||||||
args->Push(NewPointer(cls));
|
args->Push(NewPointer(cls));
|
||||||
}
|
}
|
||||||
args->Push(TypeState/*Info*/); // fixme: TypeState is not the correct type here!!!
|
args->Push(NewPointer(NewStruct("FStateParamInfo", nullptr)));
|
||||||
}
|
}
|
||||||
if (argflags != nullptr)
|
if (argflags != nullptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -388,7 +388,7 @@ static FFlagDef InventoryFlagDefs[] =
|
||||||
DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),
|
DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),
|
||||||
};
|
};
|
||||||
|
|
||||||
static FFlagDef WeaponFlagDefs[] =
|
FFlagDef WeaponFlagDefs[] =
|
||||||
{
|
{
|
||||||
// Weapon flags
|
// Weapon flags
|
||||||
DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags),
|
DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags),
|
||||||
|
@ -411,12 +411,14 @@ static FFlagDef WeaponFlagDefs[] =
|
||||||
DEFINE_FLAG(WIF, NOAUTOAIM, AWeapon, WeaponFlags),
|
DEFINE_FLAG(WIF, NOAUTOAIM, AWeapon, WeaponFlags),
|
||||||
DEFINE_FLAG(WIF, NODEATHDESELECT, AWeapon, WeaponFlags),
|
DEFINE_FLAG(WIF, NODEATHDESELECT, AWeapon, WeaponFlags),
|
||||||
DEFINE_FLAG(WIF, NODEATHINPUT, AWeapon, WeaponFlags),
|
DEFINE_FLAG(WIF, NODEATHINPUT, AWeapon, WeaponFlags),
|
||||||
|
|
||||||
DEFINE_DUMMY_FLAG(NOLMS, false),
|
|
||||||
DEFINE_FLAG(WIF, ALT_USES_BOTH, AWeapon, WeaponFlags),
|
DEFINE_FLAG(WIF, ALT_USES_BOTH, AWeapon, WeaponFlags),
|
||||||
|
|
||||||
|
DEFINE_DUMMY_FLAG(NOLMS, false),
|
||||||
DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL, false),
|
DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL, false),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static FFlagDef PlayerPawnFlagDefs[] =
|
static FFlagDef PlayerPawnFlagDefs[] =
|
||||||
{
|
{
|
||||||
// PlayerPawn flags
|
// PlayerPawn flags
|
||||||
|
|
|
@ -157,13 +157,15 @@ enum
|
||||||
ATAG_OBJECT, // pointer to an object; will be followed by GC
|
ATAG_OBJECT, // pointer to an object; will be followed by GC
|
||||||
|
|
||||||
// The following are all for documentation during debugging and are
|
// The following are all for documentation during debugging and are
|
||||||
// functionally no different than ATAG_GENERIC.
|
// functionally no different than ATAG_GENERIC (meaning they are useless because they trigger asserts all over the place.)
|
||||||
|
|
||||||
|
/*
|
||||||
ATAG_FRAMEPOINTER, // pointer to extra stack frame space for this function
|
ATAG_FRAMEPOINTER, // pointer to extra stack frame space for this function
|
||||||
ATAG_DREGISTER, // pointer to a data register
|
ATAG_DREGISTER, // pointer to a data register
|
||||||
ATAG_FREGISTER, // pointer to a float register
|
ATAG_FREGISTER, // pointer to a float register
|
||||||
ATAG_SREGISTER, // pointer to a string register
|
ATAG_SREGISTER, // pointer to a string register
|
||||||
ATAG_AREGISTER, // pointer to an address register
|
ATAG_AREGISTER, // pointer to an address register
|
||||||
|
*/
|
||||||
|
|
||||||
ATAG_RNG, // pointer to FRandom
|
ATAG_RNG, // pointer to FRandom
|
||||||
ATAG_STATE = ATAG_GENERIC, // pointer to FState (cannot have its own type because there's no means to track inside the VM.)
|
ATAG_STATE = ATAG_GENERIC, // pointer to FState (cannot have its own type because there's no means to track inside the VM.)
|
||||||
|
|
|
@ -87,7 +87,7 @@ begin:
|
||||||
OP(LFP):
|
OP(LFP):
|
||||||
ASSERTA(a); assert(sfunc != NULL); assert(sfunc->ExtraSpace > 0);
|
ASSERTA(a); assert(sfunc != NULL); assert(sfunc->ExtraSpace > 0);
|
||||||
reg.a[a] = f->GetExtra();
|
reg.a[a] = f->GetExtra();
|
||||||
reg.atag[a] = ATAG_FRAMEPOINTER;
|
reg.atag[a] = ATAG_GENERIC; // using ATAG_FRAMEPOINTER will cause endless asserts.
|
||||||
NEXTOP;
|
NEXTOP;
|
||||||
|
|
||||||
OP(LB):
|
OP(LB):
|
||||||
|
@ -461,7 +461,7 @@ begin:
|
||||||
break;
|
break;
|
||||||
case REGT_INT | REGT_ADDROF:
|
case REGT_INT | REGT_ADDROF:
|
||||||
assert(C < f->NumRegD);
|
assert(C < f->NumRegD);
|
||||||
::new(param) VMValue(®.d[C], ATAG_DREGISTER);
|
::new(param) VMValue(®.d[C], ATAG_GENERIC);
|
||||||
break;
|
break;
|
||||||
case REGT_INT | REGT_KONST:
|
case REGT_INT | REGT_KONST:
|
||||||
assert(C < sfunc->NumKonstD);
|
assert(C < sfunc->NumKonstD);
|
||||||
|
@ -473,7 +473,7 @@ begin:
|
||||||
break;
|
break;
|
||||||
case REGT_STRING | REGT_ADDROF:
|
case REGT_STRING | REGT_ADDROF:
|
||||||
assert(C < f->NumRegS);
|
assert(C < f->NumRegS);
|
||||||
::new(param) VMValue(®.s[C], ATAG_SREGISTER);
|
::new(param) VMValue(®.s[C], ATAG_GENERIC);
|
||||||
break;
|
break;
|
||||||
case REGT_STRING | REGT_KONST:
|
case REGT_STRING | REGT_KONST:
|
||||||
assert(C < sfunc->NumKonstS);
|
assert(C < sfunc->NumKonstS);
|
||||||
|
@ -485,7 +485,7 @@ begin:
|
||||||
break;
|
break;
|
||||||
case REGT_POINTER | REGT_ADDROF:
|
case REGT_POINTER | REGT_ADDROF:
|
||||||
assert(C < f->NumRegA);
|
assert(C < f->NumRegA);
|
||||||
::new(param) VMValue(®.a[C], ATAG_AREGISTER);
|
::new(param) VMValue(®.a[C], ATAG_GENERIC);
|
||||||
break;
|
break;
|
||||||
case REGT_POINTER | REGT_KONST:
|
case REGT_POINTER | REGT_KONST:
|
||||||
assert(C < sfunc->NumKonstA);
|
assert(C < sfunc->NumKonstA);
|
||||||
|
@ -512,7 +512,7 @@ begin:
|
||||||
break;
|
break;
|
||||||
case REGT_FLOAT | REGT_ADDROF:
|
case REGT_FLOAT | REGT_ADDROF:
|
||||||
assert(C < f->NumRegF);
|
assert(C < f->NumRegF);
|
||||||
::new(param) VMValue(®.f[C], ATAG_FREGISTER);
|
::new(param) VMValue(®.f[C], ATAG_GENERIC);
|
||||||
break;
|
break;
|
||||||
case REGT_FLOAT | REGT_KONST:
|
case REGT_FLOAT | REGT_KONST:
|
||||||
assert(C < sfunc->NumKonstF);
|
assert(C < sfunc->NumKonstF);
|
||||||
|
|
|
@ -2160,6 +2160,7 @@ void ZCCCompiler::InitFunctions()
|
||||||
if ((flags & VARF_Out) || (type != TypeVector2 && type != TypeVector3))
|
if ((flags & VARF_Out) || (type != TypeVector2 && type != TypeVector3))
|
||||||
{
|
{
|
||||||
type = NewPointer(type);
|
type = NewPointer(type);
|
||||||
|
flags |= VARF_Ref;
|
||||||
}
|
}
|
||||||
else if (type == TypeVector2)
|
else if (type == TypeVector2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,6 +48,7 @@ zscript/doom/cyberdemon.txt
|
||||||
zscript/doom/spidermaster.txt
|
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/deadthings.txt
|
zscript/doom/deadthings.txt
|
||||||
zscript/doom/doomammo.txt
|
zscript/doom/doomammo.txt
|
||||||
|
|
|
@ -133,6 +133,7 @@ class Actor : Thinker native
|
||||||
|
|
||||||
// DECORATE compatible functions
|
// DECORATE compatible functions
|
||||||
native bool CheckClass(class<Actor> checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false);
|
native bool CheckClass(class<Actor> checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false);
|
||||||
|
native Inventory FindInventory(class<Inventory> itemtype, bool subclass = false);
|
||||||
native int CountInv(class<Inventory> itemtype, int ptr_select = AAPTR_DEFAULT);
|
native int CountInv(class<Inventory> itemtype, int ptr_select = AAPTR_DEFAULT);
|
||||||
native float GetDistance(bool checkz, int ptr = AAPTR_TARGET);
|
native float GetDistance(bool checkz, int ptr = AAPTR_TARGET);
|
||||||
native float GetAngle(int flags, int ptr = AAPTR_DEFAULT);
|
native float GetAngle(int flags, int ptr = AAPTR_DEFAULT);
|
||||||
|
@ -471,7 +472,6 @@ class Actor : Thinker native
|
||||||
native void A_DeQueueCorpse();
|
native void A_DeQueueCorpse();
|
||||||
native void A_ClearLastHeard();
|
native void A_ClearLastHeard();
|
||||||
native bool A_SelectWeapon(class<Weapon> whichweapon, int flags = 0);
|
native bool A_SelectWeapon(class<Weapon> whichweapon, int flags = 0);
|
||||||
action native void A_Punch();
|
|
||||||
native void A_Feathers();
|
native void A_Feathers();
|
||||||
native void A_ClassBossHealth();
|
native void A_ClassBossHealth();
|
||||||
native void A_ShootGun();
|
native void A_ShootGun();
|
||||||
|
|
|
@ -829,7 +829,7 @@ enum EStateType
|
||||||
struct FStateParamInfo
|
struct FStateParamInfo
|
||||||
{
|
{
|
||||||
state mCallingState;
|
state mCallingState;
|
||||||
EStateType mStateType;
|
/*EStateType*/int mStateType;
|
||||||
int mPSPIndex;
|
int mPSPIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,44 +12,6 @@ class DoomWeapon : Weapon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Fist
|
|
||||||
//
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class Fist : Weapon
|
|
||||||
{
|
|
||||||
Default
|
|
||||||
{
|
|
||||||
Weapon.SelectionOrder 3700;
|
|
||||||
Weapon.Kickback 100;
|
|
||||||
Obituary "$OB_MPFIST";
|
|
||||||
Tag "$TAG_FIST";
|
|
||||||
+WEAPON.WIMPY_WEAPON
|
|
||||||
+WEAPON.MELEEWEAPON
|
|
||||||
}
|
|
||||||
States
|
|
||||||
{
|
|
||||||
Ready:
|
|
||||||
PUNG A 1 A_WeaponReady;
|
|
||||||
Loop;
|
|
||||||
Deselect:
|
|
||||||
PUNG A 1 A_Lower;
|
|
||||||
Loop;
|
|
||||||
Select:
|
|
||||||
PUNG A 1 A_Raise;
|
|
||||||
Loop;
|
|
||||||
Fire:
|
|
||||||
PUNG B 4;
|
|
||||||
PUNG C 4 A_Punch;
|
|
||||||
PUNG D 5;
|
|
||||||
PUNG C 4;
|
|
||||||
PUNG B 5 A_ReFire;
|
|
||||||
Goto Ready;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
|
80
wadsrc/static/zscript/doom/weaponfist.txt
Normal file
80
wadsrc/static/zscript/doom/weaponfist.txt
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Fist
|
||||||
|
//
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class Fist : Weapon
|
||||||
|
{
|
||||||
|
Default
|
||||||
|
{
|
||||||
|
Weapon.SelectionOrder 3700;
|
||||||
|
Weapon.Kickback 100;
|
||||||
|
Obituary "$OB_MPFIST";
|
||||||
|
Tag "$TAG_FIST";
|
||||||
|
+WEAPON.WIMPY_WEAPON
|
||||||
|
+WEAPON.MELEEWEAPON
|
||||||
|
}
|
||||||
|
States
|
||||||
|
{
|
||||||
|
Ready:
|
||||||
|
PUNG A 1 A_WeaponReady;
|
||||||
|
Loop;
|
||||||
|
Deselect:
|
||||||
|
PUNG A 1 A_Lower;
|
||||||
|
Loop;
|
||||||
|
Select:
|
||||||
|
PUNG A 1 A_Raise;
|
||||||
|
Loop;
|
||||||
|
Fire:
|
||||||
|
PUNG B 4;
|
||||||
|
PUNG C 4 A_Punch;
|
||||||
|
PUNG D 5;
|
||||||
|
PUNG C 4;
|
||||||
|
PUNG B 5 A_ReFire;
|
||||||
|
Goto Ready;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Code (must be attached to Actor)
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
extend class Actor
|
||||||
|
{
|
||||||
|
action void A_Punch()
|
||||||
|
{
|
||||||
|
FTranslatedLineTarget t;
|
||||||
|
|
||||||
|
if (player != null)
|
||||||
|
{
|
||||||
|
Weapon weap = player.ReadyWeapon;
|
||||||
|
if (weap != null && !weap.bDehAmmo && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite)
|
||||||
|
{
|
||||||
|
if (!weap.DepleteAmmo (weap.bAltFire))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int damage = random[Punch](1, 10) << 1;
|
||||||
|
|
||||||
|
if (FindInventory("PowerStrength"))
|
||||||
|
damage *= 10;
|
||||||
|
|
||||||
|
double ang = angle + Random2[Punch]() * (5.625 / 256);
|
||||||
|
double pitch = AimLineAttack (ang, MELEERANGE);
|
||||||
|
|
||||||
|
LineAttack (ang, MELEERANGE, pitch, damage, 'Melee', "BulletPuff", LAF_ISMELEEATTACK, t);
|
||||||
|
|
||||||
|
// turn to face target
|
||||||
|
if (t.linetarget)
|
||||||
|
{
|
||||||
|
A_PlaySound ("*fist", CHAN_WEAPON);
|
||||||
|
angle = t.angleFromSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -473,6 +473,8 @@ class Weapon : StateProvider native
|
||||||
Stop;
|
Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
native bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1);
|
||||||
|
|
||||||
native action void A_ZoomFactor(float scale = 1, int flags = 0);
|
native action void A_ZoomFactor(float scale = 1, int flags = 0);
|
||||||
native action void A_SetCrosshair(int xhair);
|
native action void A_SetCrosshair(int xhair);
|
||||||
const ZOOM_INSTANT = 1;
|
const ZOOM_INSTANT = 1;
|
||||||
|
|
Loading…
Reference in a new issue