Here is the issue.
The lasers dont spawn from the muzzle of the unmaker, it spawns from above the player or below the player, and moves weirdly when the player moves.
Does anyone know what the issue is?
Code: Select all
class Unmaykr : Doomweapon
{
const CHAN_HUM = 14;
Default
{
//$Color 14
//$NotAngled
//$Title "Unmaykr"
//$Category "Weapons"
Weapon.Slotnumber 8;
Weapon.SlotPriority 0;
Weapon.SelectionOrder 2900;
Weapon.AmmoUse 1;
Weapon.AmmoUse2 30;
Weapon.AmmoGive 80;
Weapon.AmmoType "Cell";
Weapon.AmmoType2 "Cell";
+WEAPON.NOAUTOFIRE;
+WEAPON.BFG;
+DONTGIB;
Obituary "%o was unmade by %k.";
Weapon.UpSound "Weapons/UnmaykrUp";
Inventory.Pickupmessage "\cgWhat the \ca!@#%* \cgis this?!";
Inventory.PickupSound "Weapons/UnmaykrPickup";
//AttackSound "Weapons/UnmaykrFire";
Inventory.Icon "LSGRA0";
Tag "Unmaykr";
Weapon.BobSpeed 1.2;
Weapon.BobRangeX 0.5;
Weapon.BobRangeY 1.0;
}
States
{
Ready:
TNT1 A 0 A_JumpIfInventory("DemonKeyCount", 3, "NewReady");
TNT1 A 0 A_SetCrosshair (96);
TNT1 A 0 A_ZoomFactor(1.0);
TNT1 A 0;
TNT1 AAAAA 0;
TNT1 A 0 A_StartSound("unmaykr/hum", CHAN_HUM, CHANF_LOOPING|CHANF_OVERLAP, 0.25, ATTN_NORM, 0, 0);
UNMK A 1 A_WeaponReady();
Loop;
NewReady:
TNT1 A 0;
TNT1 AAAAA 0;
TNT1 A 0 A_SetCrosshair (96);
TNT1 A 0 A_ZoomFactor(1.0);
UMYK A 1 A_UnmaykrReady();
TNT1 A 0 A_StartSound("unmaykr/hum", CHAN_HUM, CHANF_LOOPING|CHANF_OVERLAP, 0.5, ATTN_NORM, 0, 0);
UMYK "##" 1 A_WeaponReady();
Loop;
Deselect:
UNMK A 0 A_JumpIfInventory("DemonKeyCount", 3, "NewDeselect");
TNT1 A 0 A_SetCrosshair (96);
TNT1 A 0 A_ZoomFactor(1.0);
TNT1 A 0 A_StopSound(CHAN_HUM);
UNMK A 1 A_Lower();
wait;
NewDeselect:
TNT1 A 0 A_SetCrosshair (96);
TNT1 A 0 A_ZoomFactor(1.0);
TNT1 A 0 A_StopSound(CHAN_HUM);
UMYK A 1 A_Lower();
Wait;
Select:
UNMK A 0 A_JumpIfInventory("DemonKeyCount", 3, "NewDeselect");
TNT1 A 0 A_SetCrosshair (96);
TNT1 A 0 A_ZoomFactor(1.0);
UNMK A 1 A_Raise();
Wait;
NewSelect:
TNT1 A 0 A_SetCrosshair (96);
TNT1 A 0 A_ZoomFactor(1.0);
UMYK A 1 A_Raise();
Wait;
Fire:
UNMK A 0 A_JumpIfInventory("DemonKeyCount", 1, "FireUpgradeOne");
UNMK B 9 Bright
{
invoker.A_FireLaser();
}
UNMK A 4 A_ReFire();
Goto Ready;
FireUpgradeOne:
UNMK A 0 A_JumpIfInventory("DemonKeyCount", 2, "FireUpgradeTwo");
UNMK B 6 Bright
{
invoker.A_FireLaser();
}
UNMK A 3 A_ReFire();
Goto Ready;
FireUpgradeTwo:
UNMK A 0 A_JumpIfInventory("DemonKeyCount", 3, "FireUpgradeThree");
UNMK B 5 Bright
{
invoker.A_FireLaser(2, -1);
}
UNMK A 3 A_ReFire();
Goto Ready;
FireUpgradeThree:
UMYK J 5 Bright
{
invoker.A_FireLaser(3, -3, true);
}
UMYK A 3 A_ReFire("Hold1");
Goto NewReady;
Hold1:
UMYK J 5 Bright
{
invoker.A_FireLaser(3, -6, true);
}
UMYK A 3 A_ReFire("Hold2");
Goto NewReady;
Hold2:
UMYK J 5 Bright
{
invoker.A_FireLaser(3, -9, true);
}
UMYK A 3 A_ReFire("Hold3");
Goto NewReady;
Hold3:
UMYK J 5 Bright
{
invoker.A_FireLaser(3, -12, true);
}
UMYK A 3 A_ReFire();
Goto NewReady;
Flash:
TNT1 A 3 A_Light(Random(4,5));
TNT1 A 1 A_Light(3);
TNT1 A 1 A_Light(2);
TNT1 A 1 A_Light(1);
Goto LightDone;
Spawn:
LSGR A -1;
Stop;
}
// Performs a hitscan attack and draws a laser to the location hit (based on puff spawn)
// amount - the number of hitscan attacks to perform (also determines ammo used)
// angOfs - the angle to offset the hitscan attack relative to the player
// additiveOfs - if true, subtracts angOfs from the angle offset for the next hitscan attack
// if false, mirrors the angle offset for the next hitscan attack
void A_FireLaser(int amount = 1, double angOfs = 0, bool additiveOfs = false)
{
if (!owner)
return;
// Make sure we have enough ammo to fire it first
Weapon weap = owner.player.ReadyWeapon;
int ammo = owner.CountInv("Cell");
if (weap != null && self == weap)
{
if (ammo < amount)
{
owner.player.mo.PickNewWeapon(null);
return;
}
// Play the weapon's Flash state
owner.player.SetPsprite(PSP_FLASH, weap.FindState('Flash'), true);
}
owner.A_TakeInventory("Cell", amount, TIF_NOTAKEINFINITE);
owner.A_StartSound("weapons/unmaykrfire", CHAN_AUTO, CHANF_DEFAULT, 0.8, ATTN_NORM, 0, 0);
owner.player.mo.PlayAttacking2();
FTranslatedLineTarget data;
double ang = angOfs;
double slope;
int damage;
Actor puff;
// Start performing the hitscan attacks
for (int i = 0; i < amount; i++)
{
slope = owner.AimLineAttack(owner.angle+ang, 4096);
damage = random(1,8)*10;
puff = owner.LineAttack(owner.angle+ang, 4096, slope, damage, 'Hitscan', "LaserPuff", LAF_NORANDOMPUFFZ, data);
if (puff)
DrawLaser(puff.pos);
// Only offset the angle if we didn't hit an enemy
if (!data.linetarget)
{
if (additiveOfs)
ang -= angOfs;
else
ang *= -1;
}
}
}
// Draws the Unmaykr laser trail starting from the player and ending at targLoc
// targLoc - 3D coordinate that marks where the laser should end
void DrawLaser(Vector3 targLoc)
{
if (!owner)
return;
// Offset the starting point of the laser based on where the player is looking
// Forward offset of 30 and height offset of 40 are based on Doom 64 EX's data
Vector2 looking;
if (owner.pitch <= 0)
looking = AngleToVector(owner.angle, 30);
else
{
// We need to move it backwards when looking down to prevent weird visual issues
double offset = owner.pitch*2 / 3;
looking = AngleToVector(owner.angle, abs(30-offset));
if (offset > 30)
looking *= -1;
}
// Get the direction from the player to the puff
Vector3 origin = owner.pos + (looking.x,looking.y,40);
Vector3 base = targLoc - origin;
Vector3 dir = base.Unit();
double length = base.Length();
int l = 0; // Used for keeping track of when to spawn a light source in the trail
int dur = 1; // How long a group of sprites should stay alive in tics (35 is one second)
bool increaseDur = false; // Whether to increase the duration for the next group of sprites
// Traverse down the path while spawning sprites
UnmaykrLaserTrailFix trail;
Vector3 spos;
for (int i = 0; i < length; i++)
{
spos = origin + dir*i;
if (l == 32)
{
trail = UnmaykrLaserTrailFix(Spawn("UnmaykrLaserTrailFix2", spos, ALLOW_REPLACE));
l = 0;
if (increaseDur)
{
dur++;
increaseDur = false;
}
else
increaseDur = true;
}
else
trail = UnmaykrLaserTrailFix(Spawn("UnmaykrLaserTrailFix", spos, ALLOW_REPLACE));
trail.deathTimer = dur;
l++;
}
}
action void A_UnmaykrReady()
{
if(random(0,35) == 0)
{
Players[consoleplayer].psprites.frame = random(1,8);
A_StartSound("world/spark", CHAN_WEAPON, CHANF_OVERLAP, 0.250);
}
else if(level.totaltime % 16 == 0)
{
Players[consoleplayer].psprites.frame = 0;
A_StopSound(CHAN_WEAPON);
}
A_WeaponReady();
}
}
Class FullUnmaykr : CustomInventory
{
Default
{
Inventory.PickupMessage "";
}
States
{
Spawn:
LSGR A -1 Bright;
Stop;
Pickup:
TNT1 A 0 A_GiveInventory("DemonKeyCount", 3);
TNT1 A 0 A_GiveInventory("Unmaykr", 1);
TNT1 A 0 A_GiveInventory("OrangeKeyIcon", 1);
TNT1 A 0 A_GiveInventory("PurpleKeyIcon", 1);
TNT1 A 0 A_GiveInventory("CyanKeyIcon", 1);
TNT1 A 0 A_GiveInventory("Backpack", 1);
TNT1 A 0 A_GiveInventory("Cell", 600);
TNT1 A 0 A_Print("\cgYou shall forever be Eternally damned, Cheater!");
Stop;
}
}
class LaserPuff : BulletPuff
{
Default
{
Alpha 1;
VSpeed 0;
+PUFFONACTORS
+ALWAYSPUFF
+FORCEXYBILLBOARD
+NOINTERACTION
}
States
{
Spawn:
LPUF AB 3 BRIGHT A_FadeOut(0.10);
Loop;
Melee:
Stop;
}
}
class UnmaykrLaserTrailFix : Actor
{
int deathTimer;
int i;
Default
{
Radius 1;
Height 2;
Scale 0.6;
+NOINTERACTION;
+FORCEXYBILLBOARD;
}
States
{
Spawn:
UNML A 1 BRIGHT
{
if (i == deathTimer)
SetState(null);
else
i++;
}
Loop;
}
}
// Used for light source
class UnmaykrLaserTrailFix2 : UnmaykrLaserTrailFix {}