diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 4672977614..ca13ac7ee4 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -20,7 +20,6 @@ #include "g_shared/a_pickups.h" // Include all the other Doom stuff here to reduce compile time -#include "a_doomweaps.cpp" #include "a_painelemental.cpp" #include "a_scriptedmarine.cpp" diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp deleted file mode 100644 index 067a106be5..0000000000 --- a/src/g_doom/a_doomweaps.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "s_sound.h" -#include "m_random.h" -#include "a_pickups.h" -#include "d_player.h" -#include "p_pspr.h" -#include "p_local.h" -#include "gstrings.h" -#include "p_effect.h" -#include "gi.h" -#include "templates.h" -#include "vm.h" -#include "doomstat.h" -*/ - -void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int index); -static FRandom pr_firerail ("FireRail"); -static FRandom pr_bfgspray ("BFGSpray"); -static FRandom pr_oldbfg ("OldBFG"); - - -// -// [RH] A_FireRailgun -// -static void FireRailgun(AActor *self, int offset_xy, bool fromweapon) -{ - int damage; - player_t *player; - - if (NULL == (player = self->player)) - { - return; - } - - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL && fromweapon) - { - if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) - return; - - FState *flash = weapon->FindState(NAME_Flash); - if (flash != NULL) - { - P_SetSafeFlash(weapon, player, flash, (pr_firerail()&1)); - } - } - - damage = deathmatch ? 100 : 150; - - FRailParams p; - p.source = self; - p.damage = damage; - p.offset_xy = offset_xy; - P_RailAttack (&p); -} - - -DEFINE_ACTION_FUNCTION(AActor, A_FireRailgun) -{ - PARAM_ACTION_PROLOGUE(AActor); - FireRailgun(self, 0, ACTION_CALL_FROM_PSPRITE()); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_FireRailgunRight) -{ - PARAM_ACTION_PROLOGUE(AActor); - FireRailgun(self, 10, ACTION_CALL_FROM_PSPRITE()); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_FireRailgunLeft) -{ - PARAM_ACTION_PROLOGUE(AActor); - FireRailgun(self, -10, ACTION_CALL_FROM_PSPRITE()); - return 0; -} - -// -// A_FireBFG -// - -DEFINE_ACTION_FUNCTION(AActor, A_FireBFG) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL && ACTION_CALL_FROM_PSPRITE()) - { - if (!weapon->DepleteAmmo (weapon->bAltFire, true, deh.BFGCells)) - return 0; - } - - P_SpawnPlayerMissile (self, 0, 0, 0, PClass::FindActor("BFGBall"), self->Angles.Yaw, NULL, NULL, !!(dmflags2 & DF2_NO_FREEAIMBFG)); - return 0; -} - - -// -// A_BFGSpray -// Spawn a BFG explosion on every monster in view -// -enum BFG_Flags -{ - BFGF_HURTSOURCE = 1, - BFGF_MISSILEORIGIN = 2, -}; - -DEFINE_ACTION_FUNCTION(AActor, A_BFGSpray) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_DEF (spraytype, AActor) - PARAM_INT_DEF (numrays) - PARAM_INT_DEF (damagecnt) - PARAM_ANGLE_DEF (angle) - PARAM_FLOAT_DEF (distance) - PARAM_ANGLE_DEF (vrange) - PARAM_INT_DEF (defdamage) - PARAM_INT_DEF (flags) - - int i; - int j; - int damage; - DAngle an; - FTranslatedLineTarget t; - AActor *originator; - - if (spraytype == NULL) spraytype = PClass::FindActor("BFGExtra"); - if (numrays <= 0) numrays = 40; - if (damagecnt <= 0) damagecnt = 15; - if (angle == 0) angle = 90.; - if (distance <= 0) distance = 16 * 64; - if (vrange == 0) vrange = 32.; - - // [RH] Don't crash if no target - if (!self->target) - return 0; - - // [XA] Set the originator of the rays to the projectile (self) if - // the new flag is set, else set it to the player (self->target) - originator = (flags & BFGF_MISSILEORIGIN) ? self : (AActor *)(self->target); - - // offset angles from its attack angle - for (i = 0; i < numrays; i++) - { - an = self->Angles.Yaw - angle / 2 + angle / numrays*i; - - P_AimLineAttack(originator, an, distance, &t, vrange); - - if (t.linetarget != NULL) - { - AActor *spray = Spawn(spraytype, t.linetarget->PosPlusZ(t.linetarget->Height / 4), ALLOW_REPLACE); - - int dmgFlags = 0; - FName dmgType = NAME_BFGSplash; - - if (spray != NULL) - { - if ((spray->flags6 & MF6_MTHRUSPECIES && self->target->GetSpecies() == t.linetarget->GetSpecies()) || - (!(flags & BFGF_HURTSOURCE) && self->target == t.linetarget)) // [XA] Don't hit oneself unless we say so. - { - spray->Destroy(); // [MC] Remove it because technically, the spray isn't trying to "hit" them. - continue; - } - if (spray->flags5 & MF5_PUFFGETSOWNER) spray->target = self->target; - if (spray->flags3 & MF3_FOILINVUL) dmgFlags |= DMG_FOILINVUL; - if (spray->flags7 & MF7_FOILBUDDHA) dmgFlags |= DMG_FOILBUDDHA; - dmgType = spray->DamageType; - } - - if (defdamage == 0) - { - damage = 0; - for (j = 0; j < damagecnt; ++j) - damage += (pr_bfgspray() & 7) + 1; - } - else - { - // if this is used, damagecnt will be ignored - damage = defdamage; - } - - int newdam = P_DamageMobj(t.linetarget, originator, self->target, damage, dmgType, dmgFlags|DMG_USEANGLE, t.angleFromSource.Degrees); - P_TraceBleed(newdam > 0 ? newdam : damage, &t, self); - } - } - return 0; -} - -// -// A_FireOldBFG -// -// This function emulates Doom's Pre-Beta BFG -// By Lee Killough 6/6/98, 7/11/98, 7/19/98, 8/20/98 -// -// This code may not be used in other mods without appropriate credit given. -// Code leeches will be telefragged. - -DEFINE_ACTION_FUNCTION(AActor, A_FireOldBFG) -{ - PARAM_ACTION_PROLOGUE(AActor); - PClassActor *plasma[] = { PClass::FindActor("PlasmaBall1"), PClass::FindActor("PlasmaBall2") }; - AActor * mo = NULL; - - player_t *player; - bool doesautoaim = false; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = self->player->ReadyWeapon; - if (!ACTION_CALL_FROM_PSPRITE()) weapon = NULL; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) - return 0; - - doesautoaim = !(weapon->WeaponFlags & WIF_NOAUTOAIM); - weapon->WeaponFlags |= WIF_NOAUTOAIM; // No autoaiming that gun - } - self->player->extralight = 2; - - // Save values temporarily - DAngle SavedPlayerAngle = self->Angles.Yaw; - DAngle SavedPlayerPitch = self->Angles.Pitch; - for (int i = 0; i < 2; i++) // Spawn two plasma balls in sequence - { - self->Angles.Yaw += ((pr_oldbfg()&127) - 64) * (90./768); - self->Angles.Pitch += ((pr_oldbfg()&127) - 64) * (90./640); - mo = P_SpawnPlayerMissile (self, plasma[i]); - // Restore saved values - self->Angles.Yaw = SavedPlayerAngle; - self->Angles.Pitch = SavedPlayerPitch; - } - if (doesautoaim && weapon != NULL) - { // Restore autoaim setting - weapon->WeaponFlags &= ~WIF_NOAUTOAIM; - } - return 0; -} diff --git a/src/p_map.cpp b/src/p_map.cpp index 26dc3d4731..eedd503d8b 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4660,6 +4660,17 @@ void P_TraceBleed(int damage, FTranslatedLineTarget *t, AActor *puff) P_TraceBleed(damage, t->linetarget->PosPlusZ(t->linetarget->Height/2), t->linetarget, t->angleFromSource, pitch); } +DEFINE_ACTION_FUNCTION(_FTranslatedLineTarget, TraceBleed) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTranslatedLineTarget); + PARAM_INT(damage); + PARAM_OBJECT(missile, AActor); + + P_TraceBleed(damage, self, missile); + return 0; +} + + //========================================================================== // // diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 56ee12eaf7..6dac05d7b5 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6878,6 +6878,22 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) return nullptr; } } + else if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PStruct))) + { + bool writable; + if (Self->RequestAddress(ctx, &writable) && writable) + { + cls = static_cast(Self->ValueType); + Self->ValueType = NewPointer(Self->ValueType); + } + else + { + // Cannot be made writable so we cannot use its methods. + ScriptPosition.Message(MSG_ERROR, "Invalid expression on left hand side of %s\n", MethodName.GetChars()); + delete this; + return nullptr; + } + } else { ScriptPosition.Message(MSG_ERROR, "Invalid expression on left hand side of %s\n", MethodName.GetChars()); @@ -7250,18 +7266,22 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { 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) + if (ArgList[i]->ValueType != TypeNullPtr) { - ScriptPosition.Message(MSG_ERROR, "Type mismatch in reference argument", Function->SymbolName.GetChars()); - x = nullptr; - } - else - { - x = ArgList[i]; + 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]; + } } + else x = ArgList[i]; } failed |= (x == nullptr); ArgList[i] = x; @@ -7305,13 +7325,6 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { ValueType = TypeVoid; } - // If self is a struct, it will be a value type, not a reference, so we need to make an addresss request. - if (Self != nullptr && Self->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)) && !Self->ValueType->IsKindOf(RUNTIME_CLASS(PClass))) - { - bool writable; - Self->RequestAddress(ctx, &writable); - } - return this; } @@ -8852,6 +8865,13 @@ FxExpression *FxClassPtrCast::Resolve(FCompileContext &ctx) return this; } } + else if (basex->ValueType == TypeString || basex->ValueType == TypeName) + { + FxExpression *x = new FxClassTypeCast(to, basex); + basex = nullptr; + delete this; + return x->Resolve(ctx); + } // Everything else is an error. ScriptPosition.Message(MSG_ERROR, "Cannot cast %s to %s. The types are incompatible.", basex->ValueType->DescriptiveName(), to->DescriptiveName()); delete this; diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index 07d6fb8e32..031f3328b7 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -323,15 +323,15 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction case OP_CALL_K: case OP_TAIL_K: + { callfunc = (VMFunction *)func->KonstA[code[i].a].o; - callname = callfunc->Name != NAME_None ? callfunc->Name : "[anonfunc]"; - col = printf_wrapper(out, "%.23s,%d", callname, code[i].b); + col = printf_wrapper(out, "[%p],%d", callfunc, code[i].b); if (code[i].op == OP_CALL_K) { col += printf_wrapper(out, ",%d", code[i].c); } break; - + } case OP_RET: if (code[i].b != REGT_NIL) { @@ -494,7 +494,8 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction } else if (code[i].op == OP_CALL_K || code[i].op == OP_TAIL_K) { - printf_wrapper(out, " [%p]\n", callfunc); + callname = callfunc->IsKindOf(RUNTIME_CLASS(VMScriptFunction)) ? static_cast(callfunc)->PrintableName : callfunc->Name != NAME_None ? callfunc->Name : "[anonfunc]"; + printf_wrapper(out, " [%s]\n", callname); } else { diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 192089d856..fdf057b58c 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -56,6 +56,7 @@ zscript/doom/weaponchaingun.txt zscript/doom/weaponchainsaw.txt zscript/doom/weaponrlaunch.txt zscript/doom/weaponplasma.txt +zscript/doom/weaponbfg.txt zscript/doom/deadthings.txt zscript/doom/doomammo.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 2288b6c1b6..7f088154f0 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -364,7 +364,6 @@ class Actor : Thinker native // End of MBF redundant functions. native void A_MonsterRail(); - native void A_BFGSpray(class spraytype = "BFGExtra", int numrays = 40, int damagecount = 15, float angle = 90, float distance = 16*64, float vrange = 32, int damage = 0, int flags = 0); native void A_Pain(); native void A_NoBlocking(bool drop = true); void A_Fall() { A_NoBlocking(); } diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index cfdc98425b..29c60450c2 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -840,6 +840,8 @@ struct FTranslatedLineTarget Actor linetarget; double angleFromSource; bool unlinked; // found by a trace that went through an unlinked portal. + + native void TraceBleed(int damage, Actor missile); } enum EAimFlags diff --git a/wadsrc/static/zscript/doom/doomweapons.txt b/wadsrc/static/zscript/doom/doomweapons.txt index 7f8d7478fb..75f8562181 100644 --- a/wadsrc/static/zscript/doom/doomweapons.txt +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -1,6 +1,6 @@ // -------------------------------------------------------------------------- // -// Doom weapon base class +// Doom weap base class // // -------------------------------------------------------------------------- @@ -13,102 +13,51 @@ class DoomWeapon : Weapon } -// -------------------------------------------------------------------------- -// -// BFG 9000 -// -// -------------------------------------------------------------------------- -class BFG9000 : DoomWeapon +extend class StateProvider { - Default - { - Height 20; - Weapon.SelectionOrder 2800; - Weapon.AmmoUse 40; - Weapon.AmmoGive 40; - Weapon.AmmoType "Cell"; - +WEAPON.NOAUTOFIRE; - Inventory.PickupMessage "$GOTBFG9000"; - Tag "$TAG_BFG9000"; - } - States - { - Ready: - BFGG A 1 A_WeaponReady; - Loop; - Deselect: - BFGG A 1 A_Lower; - Loop; - Select: - BFGG A 1 A_Raise; - Loop; - Fire: - BFGG A 20 A_BFGsound; - BFGG B 10 A_GunFlash; - BFGG B 10 A_FireBFG; - BFGG B 20 A_ReFire; - Goto Ready; - Flash: - BFGF A 11 Bright A_Light1; - BFGF B 6 Bright A_Light2; - Goto LightDone; - Spawn: - BFUG A -1; - Stop; - OldFire: - BFGG A 10 A_BFGsound; - BFGG BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 1 A_FireOldBFG; - BFGG B 0 A_Light0; - BFGG B 20 A_ReFire; - Goto Ready; - } -} + // + // [RH] A_FireRailgun + // + action void A_FireRailgun(int offset_xy = 0) + { + if (player == null) + { + return; + } -class BFGBall : Actor -{ - Default - { - Radius 13; - Height 8; - Speed 25; - Damage 100; - Projectile; - +RANDOMIZE - RenderStyle "Add"; - Alpha 0.75; - DeathSound "weapons/bfgx"; - Obituary "$OB_MPBFG_BOOM"; - } - States - { - Spawn: - BFS1 AB 4 Bright; - Loop; - Death: - BFE1 AB 8 Bright; - BFE1 C 8 Bright A_BFGSpray; - BFE1 DEF 8 Bright; - Stop; - } -} - -class BFGExtra : Actor -{ - Default - { - +NOBLOCKMAP - +NOGRAVITY - RenderStyle "Add"; - Alpha 0.75; - DamageType "BFGSplash"; - } - States - { - Spawn: - BFE2 ABCD 8 Bright; - Stop; - } -} + Weapon weap = player.ReadyWeapon; + if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + return; + + State flash = weap.FindState('Flash'); + if (flash != null) + { + player.SetSafeFlash(weap, flash, random[FireRail]()&1); + } + + } + int damage = GetCVar("deathmatch") ? 100 : 150; + A_RailAttack(damage, offset_xy, false); // note that this function handles ammo depletion itself for Dehacked compatibility purposes. + } + + action void A_FireRailgunLeft() + { + A_FireRailgun(-10); + } + + action void A_FireRailgunRight() + { + A_FireRailgun(10); + } + + action void A_RailWait() + { + // only here to satisfy old Dehacked patches. + } + +} \ No newline at end of file diff --git a/wadsrc/static/zscript/doom/weaponbfg.txt b/wadsrc/static/zscript/doom/weaponbfg.txt new file mode 100644 index 0000000000..27f318daf9 --- /dev/null +++ b/wadsrc/static/zscript/doom/weaponbfg.txt @@ -0,0 +1,259 @@ +// -------------------------------------------------------------------------- +// +// BFG 9000 +// +// -------------------------------------------------------------------------- + +class BFG9000 : DoomWeapon +{ + Default + { + Height 20; + Weapon.SelectionOrder 2800; + Weapon.AmmoUse 40; + Weapon.AmmoGive 40; + Weapon.AmmoType "Cell"; + +WEAPON.NOAUTOFIRE; + Inventory.PickupMessage "$GOTBFG9000"; + Tag "$TAG_BFG9000"; + } + States + { + Ready: + BFGG A 1 A_WeaponReady; + Loop; + Deselect: + BFGG A 1 A_Lower; + Loop; + Select: + BFGG A 1 A_Raise; + Loop; + Fire: + BFGG A 20 A_BFGsound; + BFGG B 10 A_GunFlash; + BFGG B 10 A_FireBFG; + BFGG B 20 A_ReFire; + Goto Ready; + Flash: + BFGF A 11 Bright A_Light1; + BFGF B 6 Bright A_Light2; + Goto LightDone; + Spawn: + BFUG A -1; + Stop; + OldFire: + BFGG A 10 A_BFGsound; + BFGG BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 1 A_FireOldBFG; + BFGG B 0 A_Light0; + BFGG B 20 A_ReFire; + Goto Ready; + } +} + +//=========================================================================== +// +// Weapon code (must be attached to StateProvider) +// +//=========================================================================== + +extend class StateProvider +{ + action void A_BFGsound() + { + A_PlaySound("weapons/bfgf", CHAN_WEAPON); + } + + + // + // A_FireBFG + // + + action void A_FireBFG() + { + if (player == null) + { + return; + } + Weapon weap = player.ReadyWeapon; + if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + return; + } + + SpawnPlayerMissile("BFGBall", angle, 0, 0, 0, null, false, GetCVar("sv_nobfgaim")); + } + + + // + // A_FireOldBFG + // + // This function emulates Doom's Pre-Beta BFG + // By Lee Killough 6/6/98, 7/11/98, 7/19/98, 8/20/98 + // + // This code may not be used in other mods without appropriate credit given. + // Code leeches will be telefragged. + + action void A_FireOldBFG() + { + bool doesautoaim = false; + + if (player == null) + { + return; + } + Weapon weap = player.ReadyWeapon; + + if (invoker != weap || stateinfo == null || stateinfo.mStateType != STATE_Psprite) weap = null; + if (weap != null) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + return; + + doesautoaim = weap.bNoAutoaim; + weap.bNoAutoaim = true; + } + player.extralight = 2; + + // Save values temporarily + double SavedPlayerAngle = angle; + double SavedPlayerPitch = pitch; + for (int i = 0; i < 2; i++) // Spawn two plasma balls in sequence + { + angle += ((random[OldBFG]() & 127) - 64) * (90./768); + pitch += ((random[OldBFG]() & 127) - 64) * (90./640); + SpawnPlayerMissile (i == 0? (class)("PlasmaBall1") : (class)("PlasmaBall2")); + // Restore saved values + angle = SavedPlayerAngle; + pitch = SavedPlayerPitch; + } + // Restore autoaim setting + if (weap != null) weap.bNoAutoaim = doesautoaim; + } +} + +class BFGBall : Actor +{ + Default + { + Radius 13; + Height 8; + Speed 25; + Damage 100; + Projectile; + +RANDOMIZE + RenderStyle "Add"; + Alpha 0.75; + DeathSound "weapons/bfgx"; + Obituary "$OB_MPBFG_BOOM"; + } + States + { + Spawn: + BFS1 AB 4 Bright; + Loop; + Death: + BFE1 AB 8 Bright; + BFE1 C 8 Bright A_BFGSpray; + BFE1 DEF 8 Bright; + Stop; + } +} + +class BFGExtra : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + RenderStyle "Add"; + Alpha 0.75; + DamageType "BFGSplash"; + } + States + { + Spawn: + BFE2 ABCD 8 Bright; + Stop; + } +} + + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + // + // A_BFGSpray + // Spawn a BFG explosion on every monster in view + // + void A_BFGSpray(class spraytype = "BFGExtra", int numrays = 40, int damagecnt = 15, double ang = 90, double distance = 16*64, double vrange = 32, int defdamage = 0, int flags = 0) + { + int damage; + FTranslatedLineTarget t; + + // validate parameters + if (spraytype == null) spraytype = "BFGExtra"; + if (numrays <= 0) numrays = 40; + if (damagecnt <= 0) damagecnt = 15; + if (ang == 0) ang = 90.; + if (distance <= 0) distance = 16 * 64; + if (vrange == 0) vrange = 32.; + + // [RH] Don't crash if no target + if (!target) return; + + // [XA] Set the originator of the rays to the projectile (self) if + // the new flag is set, else set it to the player (target) + Actor originator = (flags & BFGF_MISSILEORIGIN) ? self : target; + + // offset angles from its attack ang + for (int i = 0; i < numrays; i++) + { + double an = angle - ang / 2 + ang / numrays*i; + + originator.AimLineAttack(an, distance, t, vrange); + + if (t.linetarget != null) + { + Actor spray = Spawn(spraytype, t.linetarget.pos + (0, 0, t.linetarget.Height / 4), ALLOW_REPLACE); + + int dmgFlags = 0; + Name dmgType = 'BFGSplash'; + + if (spray != null) + { + if ((spray.bMThruSpecies && target.GetSpecies() == t.linetarget.GetSpecies()) || + (!(flags & BFGF_HURTSOURCE) && target == t.linetarget)) // [XA] Don't hit oneself unless we say so. + { + spray.Destroy(); // [MC] Remove it because technically, the spray isn't trying to "hit" them. + continue; + } + if (spray.bPuffGetsOwner) spray.target = target; + if (spray.bFoilInvul) dmgFlags |= DMG_FOILINVUL; + if (spray.bFoilBuddha) dmgFlags |= DMG_FOILBUDDHA; + dmgType = spray.DamageType; + } + + if (defdamage == 0) + { + damage = 0; + for (int j = 0; j < damagecnt; ++j) + damage += Random[BFGSpray](1, 8); + } + else + { + // if this is used, damagecnt will be ignored + damage = defdamage; + } + + int newdam = t.linetarget.DamageMobj(originator, target, damage, dmgType, dmgFlags|DMG_USEANGLE, t.angleFromSource); + t.TraceBleed(newdam > 0 ? newdam : damage, self); + } + } + } +} diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 270d5e6d70..d5734e1499 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -51,13 +51,6 @@ class StateProvider : Inventory native action native void A_Lower(); action native void A_Raise(); - action native void A_FireRailgun(); - action native void A_FireRailgunLeft(); - action native void A_FireRailgunRight(); - action void A_RailWait() {} - action void A_BFGsound() { A_PlaySound("weapons/bfgf", CHAN_WEAPON); } - action native void A_FireBFG(); - action native void A_FireOldBFG(); action native void A_ReFire(statelabel flash = null); action native void A_ClearReFire(); action native void A_CheckReload();