1.1 release:

- Hexen compatibility (Combiner Patch will be updated soon).
 - Environment Map shader fixes from Doom Tournament.
 - Buffed Stunner so it's actually useful. This goes against what the Unreal
   Bible indicated but whatever, the weapon would be useless otherwise.
 - "Superweapons" now have +ALWAYSPICKUP for consistency.
 - Sneaky Strife stuff:
   - Dispersion Pistol and Stunner have reduced alert radius.
   - Rename Peacemaker sprites to avoid conflict with peasant sprites.
This commit is contained in:
Marisa the Magician 2019-12-15 14:39:11 +01:00
commit 1207748311
16 changed files with 339 additions and 281 deletions

View file

@ -73,14 +73,14 @@ This mod requires GZDoom 4.2.4 or later, and runs on top of Doom Tournament.
## In progress
- Tooltips for options.
- Extension to the Translator so it can show item descriptions and whatnot
when picking them up. Give it some usability for normal gameplay. Could
eventually extend this further to make it more like Serious Sam's NETRICSA.
- N/A, this is the 1.1 release.
## Planned
- Shifted to a 1.1 update:
- Shifted to a 1.2 update:
- Extension to the Translator so it can show item descriptions and whatnot
when picking them up. Give it some usability for normal gameplay. Could
eventually extend it further to make it more like Serious Sam's NETRICSA.
- Impaler "slice" animation for melee alt.
- Alternate flamethrower secondary that behaves more like the Unreal Bible
describes (unlit blobs at a rate of 4 per second that catch on fire with

BIN
graphics/icons/ItemABox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -8,7 +8,7 @@ Model "Peacerocket"
USEACTORPITCH
USEACTORROLL
FrameIndex PEAR A 0 0
FrameIndex PEMR A 0 0
}
Model "PeaceFragment"
@ -40,40 +40,40 @@ Model "Peacebarrel"
USEACTORROLL
// unfold
FrameIndex PEAM A 0 0
FrameIndex PEAM B 0 1
FrameIndex PEAM C 0 2
FrameIndex PEAM D 0 3
FrameIndex PEAM E 0 4
FrameIndex PEAM F 0 5
FrameIndex PEAM G 0 6
FrameIndex PEAM H 0 7
FrameIndex PEAM I 0 8
FrameIndex PEAM J 0 9
FrameIndex PEAM K 0 10
FrameIndex PEAM L 0 11
FrameIndex PEAM M 0 12
FrameIndex PEAM N 0 13
FrameIndex PEAM O 0 14
FrameIndex PEAM P 0 15
FrameIndex PEAM Q 0 16
FrameIndex PEAM R 0 17
FrameIndex PEAM S 0 18
FrameIndex PEAM T 0 19
FrameIndex PEAM U 0 20
FrameIndex PEAM V 0 21
FrameIndex PEAM W 0 22
FrameIndex PEAM X 0 23
FrameIndex PEAM Y 0 24
FrameIndex PEAM Z 0 25
FrameIndex PEAM [ 0 26
FrameIndex PEAM \ 0 27
FrameIndex PEAM ] 0 28
FrameIndex PEMM A 0 0
FrameIndex PEMM B 0 1
FrameIndex PEMM C 0 2
FrameIndex PEMM D 0 3
FrameIndex PEMM E 0 4
FrameIndex PEMM F 0 5
FrameIndex PEMM G 0 6
FrameIndex PEMM H 0 7
FrameIndex PEMM I 0 8
FrameIndex PEMM J 0 9
FrameIndex PEMM K 0 10
FrameIndex PEMM L 0 11
FrameIndex PEMM M 0 12
FrameIndex PEMM N 0 13
FrameIndex PEMM O 0 14
FrameIndex PEMM P 0 15
FrameIndex PEMM Q 0 16
FrameIndex PEMM R 0 17
FrameIndex PEMM S 0 18
FrameIndex PEMM T 0 19
FrameIndex PEMM U 0 20
FrameIndex PEMM V 0 21
FrameIndex PEMM W 0 22
FrameIndex PEMM X 0 23
FrameIndex PEMM Y 0 24
FrameIndex PEMM Z 0 25
FrameIndex PEMM [ 0 26
FrameIndex PEMM \ 0 27
FrameIndex PEMM ] 0 28
// launch
FrameIndex PEAL A 0 29
FrameIndex PEAL B 0 30
FrameIndex PEAL C 0 31
FrameIndex PEAL D 0 32
FrameIndex PEML A 0 29
FrameIndex PEML B 0 30
FrameIndex PEML C 0 31
FrameIndex PEML D 0 32
}
Model "Peacemaker"
@ -85,11 +85,11 @@ Model "Peacemaker"
ZOffset 5
Scale 0.16 -0.16 0.16
FrameIndex PEAP B 1 0
FrameIndex PEMP B 1 0
ZOffset 9
ROTATING
FrameIndex PEAP A 1 0
FrameIndex PEMP A 1 0
}
Model "Peacemaker"
@ -102,57 +102,57 @@ Model "Peacemaker"
Offset 7.5 -15 -7.5
// Select
FrameIndex PEAS A 0 0
FrameIndex PEAS B 0 1
FrameIndex PEAS C 0 2
FrameIndex PEAS D 0 3
FrameIndex PEAS E 0 4
FrameIndex PEAS F 0 5
FrameIndex PEAS G 0 6
FrameIndex PEAS H 0 7
FrameIndex PEAS I 0 8
FrameIndex PEAS J 0 9
FrameIndex PEAS K 0 10
FrameIndex PEAS L 0 11
FrameIndex PEAS M 0 12
FrameIndex PEAS N 0 13
FrameIndex PEAS O 0 14
FrameIndex PEAS P 0 15
FrameIndex PEAS Q 0 16
FrameIndex PEAS R 0 17
FrameIndex PEAS S 0 18
FrameIndex PEAS T 0 19
FrameIndex PEMS A 0 0
FrameIndex PEMS B 0 1
FrameIndex PEMS C 0 2
FrameIndex PEMS D 0 3
FrameIndex PEMS E 0 4
FrameIndex PEMS F 0 5
FrameIndex PEMS G 0 6
FrameIndex PEMS H 0 7
FrameIndex PEMS I 0 8
FrameIndex PEMS J 0 9
FrameIndex PEMS K 0 10
FrameIndex PEMS L 0 11
FrameIndex PEMS M 0 12
FrameIndex PEMS N 0 13
FrameIndex PEMS O 0 14
FrameIndex PEMS P 0 15
FrameIndex PEMS Q 0 16
FrameIndex PEMS R 0 17
FrameIndex PEMS S 0 18
FrameIndex PEMS T 0 19
// Idle
FrameIndex PEAI A 0 20
FrameIndex PEMI A 0 20
// Down
FrameIndex PEAD A 0 22
FrameIndex PEAD B 0 23
FrameIndex PEAD C 0 24
FrameIndex PEAD D 0 25
FrameIndex PEAD E 0 26
FrameIndex PEAD F 0 27
FrameIndex PEAD G 0 28
FrameIndex PEAD H 0 29
FrameIndex PEAD I 0 30
FrameIndex PEMD A 0 22
FrameIndex PEMD B 0 23
FrameIndex PEMD C 0 24
FrameIndex PEMD D 0 25
FrameIndex PEMD E 0 26
FrameIndex PEMD F 0 27
FrameIndex PEMD G 0 28
FrameIndex PEMD H 0 29
FrameIndex PEMD I 0 30
// Throw
FrameIndex PEAF A 0 32
FrameIndex PEAF B 0 33
FrameIndex PEAF C 0 34
FrameIndex PEAF D 0 35
FrameIndex PEAF E 0 36
FrameIndex PEAF F 0 37
FrameIndex PEAF G 0 38
FrameIndex PEAF H 0 39
FrameIndex PEAF I 0 40
FrameIndex PEMF A 0 32
FrameIndex PEMF B 0 33
FrameIndex PEMF C 0 34
FrameIndex PEMF D 0 35
FrameIndex PEMF E 0 36
FrameIndex PEMF F 0 37
FrameIndex PEMF G 0 38
FrameIndex PEMF H 0 39
FrameIndex PEMF I 0 40
// Count (0-9)
FrameIndex PEAC A 0 43
FrameIndex PEAC B 0 44
FrameIndex PEAC C 0 45
FrameIndex PEAC D 0 46
FrameIndex PEAC E 0 47
FrameIndex PEAC F 0 48
FrameIndex PEAC G 0 49
FrameIndex PEAC H 0 50
FrameIndex PEAC I 0 51
FrameIndex PEAC J 0 52
FrameIndex PEMC A 0 43
FrameIndex PEMC B 0 44
FrameIndex PEMC C 0 45
FrameIndex PEMC D 0 46
FrameIndex PEMC E 0 47
FrameIndex PEMC F 0 48
FrameIndex PEMC G 0 49
FrameIndex PEMC H 0 50
FrameIndex PEMC I 0 51
FrameIndex PEMC J 0 52
}

View file

@ -5,5 +5,5 @@ vec4 ProcessTexel()
float mask = texture(masktex,vTexCoord.st).x;
vec3 eyedir = normalize(uCameraPos.xyz-pixelpos.xyz);
vec3 norm = reflect(eyedir,normalize(vWorldNormal.xyz));
return vec4(base.rgb+texture(envtex,norm.xz*0.5).rgb*mask,base.a);
return vec4(base.rgb+texture(envtex,norm.xz*0.5+0.5).rgb*mask,base.a);
}

View file

@ -13,5 +13,5 @@ vec4 ProcessTexel()
float mask = texture(masktex,vTexCoord.st).x;
vec3 eyedir = normalize(uCameraPos.xyz-pixelpos.xyz);
vec3 norm = reflect(eyedir,normalize(vWorldNormal.xyz));
return vec4(base.rgb+texture(envtex,norm.xz*0.5).rgb*mask,base.a);
return vec4(base.rgb+texture(envtex,norm.xz*0.5+0.5).rgb*mask,base.a);
}

View file

@ -1,4 +1,4 @@
Sprite "PEAPA0",1,1{}
Sprite "PEASA0",1,1{}
Sprite "PEAMA0",1,1{}
Sprite "PEARA0",1,1{}
Sprite "PEMPA0",1,1{}
Sprite "PEMSA0",1,1{}
Sprite "PEMMA0",1,1{}
Sprite "PEMRA0",1,1{}

View file

@ -536,7 +536,7 @@ Class Automag : UnrealWeapon
{
invoker.clipout = true;
A_Overlay(-9999,null);
A_PlaySound("automag/click",CHAN_WEAPON,!Dampener.Active(self)?1.:.1);
A_PlaySound("automag/click",CHAN_ITEM,!Dampener.Active(self)?1.:.1);
}
AUTR ABCDEFGHIJKLMNOPQRSTUVWXY 1;
AUTD ABCD 1;

View file

@ -432,6 +432,7 @@ Class BigGun : UnrealWeapon
Weapon.AmmoGive 4;
Inventory.RespawnTics 2100;
+INVENTORY.IGNORESKILL;
+INVENTORY.ALWAYSPICKUP;
UTWeapon.DropAmmo 4;
BigGun.ClipCount 4;
+EXTREMEDEATH;

View file

@ -323,7 +323,7 @@ Class DispersionAmmo : Actor
action void A_DispExpl()
{
UTMainHandler.DoKnockback(tracer,(cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch)),6000);
A_AlertMonsters();
A_AlertMonsters(gameinfo.gametype&GAME_Strife?100:0);
A_SprayDecal("RazorBlast",20);
Spawn(invoker.LightClass,pos);
Actor a;
@ -344,6 +344,12 @@ Class DispersionAmmo : Actor
UTMainHandler.DoBlast(self,80,6000);
A_Explode(GetMissileDamage(0,0),80);
}
override int DoSpecialDamage( Actor target, int damage, Name damagetype )
{
if ( gameinfo.gametype&GAME_Strife )
target.DaggerAlert(self.target);
return damage;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
@ -542,7 +548,7 @@ Class DispersionPistol : UnrealWeapon
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
UTMainHandler.DoSwing(self,(FRandom[DPistol](-0.1,-0.3),FRandom[DPistol](-0.1,0.3)),2+invoker.upgradelevel*0.5,-0.3,3,SWING_Spring,0,3+invoker.upgradelevel);
if ( !Dampener.Active(self) ) A_AlertMonsters();
if ( !Dampener.Active(self) ) A_AlertMonsters(gameinfo.gametype&GAME_Strife?120:0);
A_QuakeEx(2,2,2,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
@ -615,7 +621,7 @@ Class DispersionPistol : UnrealWeapon
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
double ss = 0.5+invoker.chargesize*0.3;
UTMainHandler.DoSwing(self,(FRandom[DPistol](-0.1,-0.3)*ss,FRandom[DPistol](-0.1,0.3))*ss,2+invoker.upgradelevel*0.5,-0.3,3,SWING_Spring,0,3+invoker.upgradelevel);
if ( !Dampener.Active(self) ) A_AlertMonsters();
if ( !Dampener.Active(self) ) A_AlertMonsters(gameinfo.gametype&GAME_Strife?120:0);
int qs = int(1+invoker.chargesize*0.3);
A_QuakeEx(qs,qs,qs,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;

View file

@ -250,6 +250,7 @@ Class SMiniGun : UnrealWeapon
Weapon.AmmoGive 32;
Inventory.RespawnTics 2100;
+INVENTORY.IGNORESKILL;
+INVENTORY.ALWAYSPICKUP;
UTWeapon.DropAmmo 4;
}
States

View file

@ -1,90 +1,6 @@
// Backpack that only gives ammo for valid weapons
Class UnrealBackpack : BackpackItem replaces Backpack
Class UnrealBackpack : UTBackpack
{
override Inventory CreateCopy( Actor other )
{
// Find every unique type of ammoitem. Give it to the player if
// he doesn't have it already, and double its maximum capacity.
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
let type = (class<Ammo>)(AllActorClasses[i]);
if ( !type || (type.GetParentClass() != 'Ammo') ) continue;
// check that it's for a valid weapon
bool isvalid = false;
for ( int j=0; j<AllActorClasses.Size(); j++ )
{
let type2 = (class<Weapon>)(AllActorClasses[j]);
if ( !type2 ) continue;
let rep = GetReplacement(type2);
if ( (rep != type2) && !(rep is "DehackedPickup") ) continue;
readonly<Weapon> weap = GetDefaultByType(type2);
if ( !other.player || !other.player.weapons.LocateWeapon(type2) || weap.bCheatNotWeapon ) continue;
if ( (weap.AmmoType1 == type) || (weap.AmmoType2 == type) )
{
isvalid = true;
break;
}
}
if ( !isvalid ) continue;
let ammoitem = Ammo(other.FindInventory(type));
int amount = GetDefaultByType(type).BackpackAmount;
// don't give these at all
if ( (amount <= 0) && (GetDefaultByType(type).BackpackMaxAmount == GetDefaultByType(type).MaxAmount) ) continue;
// extra ammo in baby mode and nightmare mode
if ( !bIgnoreSkill ) amount = int(amount*G_SkillPropertyFloat(SKILLP_AmmoFactor));
if ( amount < 0 ) amount = 0;
if ( !ammoitem )
{
// The player did not have the ammoitem. Add it.
ammoitem = Ammo(Spawn(type));
ammoitem.Amount = bDepleted?0:amount;
if ( ammoitem.BackpackMaxAmount > ammoitem.MaxAmount )
ammoitem.MaxAmount = ammoitem.BackpackMaxAmount;
if ( ammoitem.Amount > ammoitem.MaxAmount )
ammoitem.Amount = ammoitem.MaxAmount;
ammoitem.AttachToOwner(other);
}
else
{
// The player had the ammoitem. Give some more.
if ( ammoitem.MaxAmount < ammoitem.BackpackMaxAmount )
ammoitem.MaxAmount = ammoitem.BackpackMaxAmount;
if ( !bDepleted && (ammoitem.Amount < ammoitem.MaxAmount) )
{
ammoitem.Amount += amount;
if ( ammoitem.Amount > ammoitem.MaxAmount )
ammoitem.Amount = ammoitem.MaxAmount;
}
}
}
return Inventory.CreateCopy(other);
}
override bool HandlePickup( Inventory item )
{
// Since you already have a backpack, that means you already have every
// kind of ammo in your inventory, so we don't need to look at the
// entire PClass list to discover what kinds of ammo exist, and we don't
// have to alter the MaxAmount either.
if ( item is 'BackpackItem' )
{
for ( let probe = Owner.Inv; probe; probe = probe.Inv )
{
if ( probe.GetParentClass() != 'Ammo' ) continue;
if ( probe.Amount >= probe.MaxAmount && !sv_unlimited_pickup ) continue;
int amount = Ammo(probe).Default.BackpackAmount;
// extra ammo in baby mode and nightmare mode
if ( !bIgnoreSkill )
amount = int(amount*G_SkillPropertyFloat(SKILLP_AmmoFactor));
probe.Amount += amount;
if ( (probe.Amount > probe.MaxAmount) && !sv_unlimited_pickup )
probe.Amount = probe.MaxAmount;
}
// The pickup always succeeds, even if you didn't get anything
item.bPickupGood = true;
return true;
}
return false;
}
override void DoPickupSpecial( Actor toucher )
{
Super.DoPickupSpecial(toucher);
@ -114,18 +30,6 @@ Class UnrealBackpack : BackpackItem replaces Backpack
}
}
}
Default
{
Tag "$T_BACKPACK";
Inventory.PickupMessage "$I_BACKPACK";
Inventory.RespawnTics 2100;
}
States
{
Spawn:
BPAK A -1;
Stop;
}
}
Class UTranslator : UnrealInventory

View file

@ -245,6 +245,7 @@ Class OLSMP : UnrealWeapon
UTWeapon.DropAmmo 50;
OLSMP.ClipCount 100;
+UNREALWEAPON.NOFIRSTGIVE;
+INVENTORY.ALWAYSPICKUP;
}
States
{
@ -337,7 +338,7 @@ Class OLSMP : UnrealWeapon
invoker.clipout = true;
A_Overlay(-9999,null);
A_WeaponOffset(0,32); // fix sudden psprite lowering
A_PlaySound("automag/click",CHAN_WEAPON,!Dampener.Active(self)?1.:.1,pitch:0.8);
A_PlaySound("automag/click",CHAN_ITEM,!Dampener.Active(self)?1.:.1,pitch:0.8);
}
AUTR ABCDEFGHIJKLMNOPQRSTUVWXY 1;
AUTD ABCD 1;

View file

@ -157,7 +157,7 @@ Class PeaceRocket : Actor
States
{
Spawn:
PEAR A 1
PEMR A 1
{
roll += 5.;
A_SeekTargets();
@ -340,10 +340,10 @@ Class PeaceBarrel : Actor
States
{
Spawn:
PEAM A -1;
PEMM A -1;
Stop;
Bounce:
PEAM A 0
PEMM A 0
{
if ( BlockingFloor ) A_AlignSelf();
else pitch = roll = 0;
@ -351,59 +351,59 @@ Class PeaceBarrel : Actor
}
Goto Spawn;
Death:
PEAM A 1 A_CheckFloor(1);
PEMM A 1 A_CheckFloor(1);
Wait;
PEAM A 4 A_AlignSelf();
PEAM A 35
PEMM A 4 A_AlignSelf();
PEMM A 35
{
A_PlaySound((special1<=0)?"eightball/seeklost":"eightball/seeklock",CHAN_AUTO);
A_AlertMonsters();
return A_JumpIf(--special1<0,1);
}
Wait;
PEAM A 0 A_JumpIf(bAMBUSH,"Detonate");
PEAM A 3 A_PlaySound("peace/open",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEAM B 3;
PEAM C 3 A_PlaySound("peace/open",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEAM D 3 A_PlaySound("transloc/bounce",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEAM E 3 A_PlaySound("peace/open",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEAM F 3
PEMM A 0 A_JumpIf(bAMBUSH,"Detonate");
PEMM A 3 A_PlaySound("peace/open",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEMM B 3;
PEMM C 3 A_PlaySound("peace/open",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEMM D 3 A_PlaySound("transloc/bounce",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEMM E 3 A_PlaySound("peace/open",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEMM F 3
{
A_PlaySound("transloc/bounce",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
A_PlaySound("transloc/bounce",CHAN_AUTO,.5,pitch:FRandom[Peace](0.8,1.2));
}
PEAM G 3 A_PlaySound("peace/open",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEAM H 3
PEMM G 3 A_PlaySound("peace/open",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEMM H 3
{
A_PlaySound("transloc/bounce",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
A_PlaySound("transloc/bounce",CHAN_AUTO,.5,pitch:FRandom[Peace](0.8,1.2));
}
PEAM I 3;
PEAM J 3
PEMM I 3;
PEMM J 3
{
A_PlaySound("transloc/bounce",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
A_PlaySound("transloc/bounce",CHAN_AUTO,.5,pitch:FRandom[Peace](0.8,1.2));
}
PEAM K 3 A_PlaySound("eightball/rotate",CHAN_AUTO,.1);
PEAM L 3 A_PlaySound("transloc/bounce",CHAN_AUTO,.5,pitch:FRandom[Peace](0.8,1.2));
PEAM M 3;
PEAM N 3 A_PlaySound("eightball/rotate",CHAN_AUTO,.1);
PEAM OPQ 3;
PEAM R 3 A_PlaySound("eightball/rotate",CHAN_AUTO,.1);
PEAM STU 3;
PEAM V 3 A_PlaySound("eightball/rotate",CHAN_AUTO,.1);
PEAM XYZ[\] 3;
PEAM ] 35;
PEAM ] 0 A_FireRocket(0);
PEAL A 20;
PEAL A 0 A_FireRocket(1);
PEAL B 20;
PEAL B 0 A_FireRocket(2);
PEAL C 20;
PEAL C 0 A_FireRocket(3);
PEAL D 20;
PEMM K 3 A_PlaySound("eightball/rotate",CHAN_AUTO,.1);
PEMM L 3 A_PlaySound("transloc/bounce",CHAN_AUTO,.5,pitch:FRandom[Peace](0.8,1.2));
PEMM M 3;
PEMM N 3 A_PlaySound("eightball/rotate",CHAN_AUTO,.1);
PEMM OPQ 3;
PEMM R 3 A_PlaySound("eightball/rotate",CHAN_AUTO,.1);
PEMM STU 3;
PEMM V 3 A_PlaySound("eightball/rotate",CHAN_AUTO,.1);
PEMM XYZ[\] 3;
PEMM ] 35;
PEMM ] 0 A_FireRocket(0);
PEML A 20;
PEML A 0 A_FireRocket(1);
PEML B 20;
PEML B 0 A_FireRocket(2);
PEML C 20;
PEML C 0 A_FireRocket(3);
PEML D 20;
Detonate:
PEAM A 20;
PEMM A 20;
BlowUp:
TNT1 A 0 A_BlowUp();
SSMX ABCDEFGHIJ 2 Bright;
@ -492,19 +492,19 @@ Class Peacemaker : UnrealWeapon
States
{
Spawn:
PEAP A -1;
PEMP A -1;
Stop;
PEAP B -1;
PEMP B -1;
Stop;
Select:
PEAS A 1 A_Raise(int.max);
PEMS A 1 A_Raise(int.max);
Wait;
Ready:
PEAS ABCDEFGHIJ 2 A_WeaponReady(WRF_NOFIRE);
PEAS K 0 A_PlaySound("peace/up",CHAN_ITEM,.4);
PEAS KLMNOPQRST 2 A_WeaponReady(WRF_NOFIRE);
PEMS ABCDEFGHIJ 2 A_WeaponReady(WRF_NOFIRE);
PEMS K 0 A_PlaySound("peace/up",CHAN_ITEM,.4);
PEMS KLMNOPQRST 2 A_WeaponReady(WRF_NOFIRE);
Idle:
PEAI A 1
PEMI A 1
{
A_CheckReload();
A_WeaponReady();
@ -522,45 +522,45 @@ Class Peacemaker : UnrealWeapon
}
Wait;
Fire:
PEAC A 1 A_StartCount();
PEAC # 1 A_CountUp(1);
PEMC A 1 A_StartCount();
PEMC # 1 A_CountUp(1);
Wait;
PEAF ABCD 2;
PEAF E 0
PEMF ABCD 2;
PEMF E 0
{
A_PlaySound("peace/down",CHAN_ITEM,.4);
UTMainHandler.DoSwing(self,(FRandom[Peace](-0.1,-0.04),FRandom[Peace](0.4,0.6)),3,0,7,SWING_Spring,3,0.8);
}
PEAF EFG 2;
PEAF H 0
PEMF EFG 2;
PEMF H 0
{
UTMainHandler.DoSwing(self,(FRandom[Peace](0.08,0.12),FRandom[Peace](-1.2,-0.9)),4,0,6,SWING_Spring,3,1.5);
}
PEAF HI 2; // hello
PEAF I -1 A_PeacemakerThrow();
PEMF HI 2; // hello
PEMF I -1 A_PeacemakerThrow();
Stop;
AltFire:
PEAC A 1 A_StartCount();
PEAC # 1 A_CountUp(1);
PEMC A 1 A_StartCount();
PEMC # 1 A_CountUp(1);
Wait;
PEAF ABCD 2;
PEAF E 0
PEMF ABCD 2;
PEMF E 0
{
A_PlaySound("peace/down",CHAN_ITEM,.4);
UTMainHandler.DoSwing(self,(FRandom[Peace](-0.1,-0.04),FRandom[Peace](0.4,0.6)),3,0,7,SWING_Spring,3,0.8);
}
PEAF EFG 2;
PEAF H 0
PEMF EFG 2;
PEMF H 0
{
UTMainHandler.DoSwing(self,(FRandom[Peace](0.08,0.12),FRandom[Peace](-1.2,-0.9)),4,0,6,SWING_Spring,3,1.5);
}
PEAF HI 2; // howdy
PEAF I -1 A_PeacemakerThrow(true);
PEMF HI 2; // howdy
PEMF I -1 A_PeacemakerThrow(true);
Stop;
Deselect:
PEAD A 0 A_JumpIfNoAmmo("EmptyDeselect");
PEAD ABCDEFGHI 1;
PEAD J 1 A_Lower(int.max);
PEMD A 0 A_JumpIfNoAmmo("EmptyDeselect");
PEMD ABCDEFGHI 1;
PEMD J 1 A_Lower(int.max);
EmptyDeselect:
TNT1 A 1 A_Lower(int.max);
Wait;

View file

@ -167,7 +167,7 @@ Class StunProj : Actor
SetOrigin(t.Results.HitPos-t.Results.HitVector*4,false);
StunExplode();
Actor a = t.Results.HitActor;
a.DamageMobj(self,target,max(1,int(4*specialf1)),'jolted',DMG_USEANGLE,atan2(t.Results.HitVector.y,t.Results.HitVector.x));
a.DamageMobj(self,target,max(1,int(10*specialf1)),'jolted',DMG_USEANGLE,atan2(t.Results.HitVector.y,t.Results.HitVector.x));
if ( !a.bDONTTHRUST )
{
UTMainHandler.DoKnockback(a,t.Results.HitVector,(bAMBUSH?-22000:26000)*specialf1);
@ -208,10 +208,9 @@ Class StunProj : Actor
{
moving = false;
SetStateLabel("Death");
A_Explode(int(0.6*specialf1),50);
A_QuakeEx(1,1,1,3,0,250,"",QF_RELATIVE|QF_SCALEDOWN,falloff:120,rollintensity:0.2);
A_PlaySound("stun/hit",CHAN_VOICE,pitch:FRandom[Stunner](1.5,1.9)-0.08*specialf1);
UTMainHandler.DoBlast(self,50,(bAMBUSH?-7000:11000)*specialf1);
A_AlertMonsters(gameinfo.gametype&GAME_Strife?100:0);
Vector3 dir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
int numpt = Random[ExploS](10,15);
for ( int i=0; i<numpt; i++ )
@ -223,6 +222,12 @@ Class StunProj : Actor
s.vel = pvel;
}
}
override int DoSpecialDamage( Actor target, int damage, Name damagetype )
{
if ( gameinfo.gametype&GAME_Strife )
target.DaggerAlert(self.target);
return damage;
}
Default
{
Obituary "$O_STUNNER";
@ -237,6 +242,7 @@ Class StunProj : Actor
+NODAMAGETHRUST;
+NOTELEPORT;
+FORCEXYBILLBOARD;
+NOEXTREMEDEATH;
}
States
{
@ -368,7 +374,7 @@ Class Stunner : UnrealWeapon
LineTrace(angle,60,BulletSlope(),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
if ( d.HitType == TRACE_HitActor )
{
int dmg = int(5*invoker.chargesize);
int dmg = int(12*invoker.chargesize);
if ( d.HitLocation.z >= (d.HitActor.pos.z+d.HitActor.height*0.81) )
dmg = d.HitActor.DamageMobj(invoker,self,dmg*2,'Decapitated',DMG_THRUSTLESS);
else dmg = d.HitActor.DamageMobj(invoker,self,dmg,'impact',DMG_THRUSTLESS);
@ -405,7 +411,7 @@ Class Stunner : UnrealWeapon
A_OverlayFlags(-2,PSPF_RenderStyle,true);
A_OverlayRenderStyle(-2,STYLE_Add);
StunnerAmmo(weap.Ammo1).rechargephase = 0;
if ( !Dampener.Active(self) ) A_AlertMonsters();
if ( !Dampener.Active(self) && !(gameinfo.gametype&GAME_Strife) ) A_AlertMonsters();
}
action State A_ChargeUp()
{
@ -416,7 +422,7 @@ Class Stunner : UnrealWeapon
StunnerAmmo(weap.Ammo1).rechargephase = 0;
UTMainHandler.DoSwing(self,(FRandom[Stunner](-1,1),FRandom[Stunner](-1,1)),0.02*invoker.chargesize,0,2,SWING_Spring);
A_WeaponOffset(FRandom[Stunner](-1,1)*1.2*invoker.chargesize,32+FRandom[Stunner](-1,1)*1.2*invoker.chargesize);
if ( !Dampener.Active(self) ) A_AlertMonsters();
if ( !Dampener.Active(self) && !(gameinfo.gametype&GAME_Strife) ) A_AlertMonsters();
if ( invoker.chargesize >= 5. )
{
invoker.count += 1./35.;
@ -451,6 +457,7 @@ Class Stunner : UnrealWeapon
Weapon.AmmoGive 50;
UTWeapon.DropAmmo 50;
+WEAPON.WIMPY_WEAPON;
+NOEXTREMEDEATH;
}
States
{

View file

@ -682,6 +682,7 @@ Class UnrealInventory : Inventory
Super.AttachToOwner(other);
if ( !Charge ) Charge = DefaultCharge;
// it's annoying to set this per-subclass
if ( !(gameinfo.gametype&GAME_Hexen) )
InterHubAmount = bUNLIMITEDCOPIES?int.max:MaxAmount;
}
override bool HandlePickup( Inventory item )
@ -950,6 +951,52 @@ Class UNothing : Actor
}
}
Class HexenEitherOrSession : Thinker
{
Array<Class<Actor> > done;
private bool IsAvailable( Class<Actor> item )
{
let ti = ThinkerIterator.Create(item);
Actor a;
while ( a = Actor(ti.Next()) ) return true;
for ( int i=0; i<done.Size(); i++ ) if ( done[i] == item ) return true;
return false;
}
void MarkDone( Class<Actor> item )
{
for ( int i=0; i<done.Size(); i++ ) if ( done[i] == item ) return;
done.Push(item);
}
void MarkUnDone( Class<Actor> item )
{
for ( int i=0; i<done.Size(); i++ )
{
if ( done[i] != item ) continue;
done.Delete(i);
i--;
}
}
Class<Actor> EitherOr( Class<Actor> a, Class<Actor> b, bool allowed = true )
{
if ( !allowed ) return a;
if ( IsAvailable(a) )
{
MarkDone(a);
if ( IsAvailable(b) )
{
MarkDone(b);
if ( Random[Replacements](0,1) ) return b;
return a;
}
return b;
}
return a;
}
}
Class UnrealMainHandler : EventHandler
{
Array<AmmoUsedInSlot> AmmoSlots;
@ -971,6 +1018,25 @@ Class UnrealMainHandler : EventHandler
break;
}
}
private bool IsAvailable( Class<Actor> item )
{
let ti = ThinkerIterator.Create(item);
Actor a;
while ( a = Actor(ti.Next()) ) return true;
return false;
}
private Class<Actor> EitherOr( Class<Actor> a, Class<Actor> b, bool allowed = true )
{
let ti = ThinkerIterator.Create("HexenEitherOrSession",Thinker.STAT_STATIC);
HexenEitherOrSession hs = HexenEitherOrSession(ti.Next());
if ( !hs )
{
hs = new("HexenEitherOrSession");
hs.ChangeStatNum(Thinker.STAT_STATIC);
hs.done.Clear();
}
return hs.EitherOr(a,b,allowed);
}
override void CheckReplacement( ReplaceEvent e )
{
if ( e.IsFinal ) return;
@ -1140,16 +1206,16 @@ Class UnrealMainHandler : EventHandler
else if ( Random[Replacements](0,1) ) e.Replacement = 'UBioAmmo';
else e.Replacement = 'URifleAmmo';
}
else if ( (e.Replacee == 'InvulnerabilitySphere') || (e.Replacee == 'ArtiInvulnerability') ) e.Replacement = 'PowerShield';
else if ( (e.Replacee == 'InvulnerabilitySphere') || (e.Replacee == 'ArtiInvulnerability') || (e.Replacee == 'ArtiInvulnerability2') ) e.Replacement = 'PowerShield';
else if ( (e.Replacee == 'Berserk') || (e.Replacee == 'ArtiTomeOfPower') )
{
if ( sting_msentry && !Random[Replacements](0,9) ) e.Replacement = 'SentryItem';
else if ( ((sting_proto && sting_dubious) || sting_olsmp) && !Random[Replacements](0,2) ) e.Replacement = 'WeaponPowerUp';
else e.Replacement = 'Amplifier';
}
else if ( e.Replacee == 'ArtiEgg' ) e.Replacement = 'VoiceBox';
else if ( (e.Replacee == 'ArtiEgg') || (e.Replacee == 'ArtiPork') ) e.Replacement = 'VoiceBox';
else if ( (e.Replacee == 'Soulsphere') || (e.Replacee == 'ArtiSuperHealth') ) e.Replacement = 'SuperHealth';
else if ( e.Replacee == 'Megasphere' ) e.Replacement = 'ShieldBelt';
else if ( (e.Replacee == 'Megasphere') || (e.Replacee == 'ArtiBoostArmor') ) e.Replacement = 'ShieldBelt';
else if ( (e.Replacee == 'Allmap') || (e.Replacee == 'SuperMap') )
{
if ( sting_proto && Random[Replacements](0,2) ) e.Replacement = 'MotionDetector';
@ -1158,16 +1224,18 @@ Class UnrealMainHandler : EventHandler
else if ( (e.Replacee == 'BlurSphere') || (e.Replacee == 'ArtiInvisibility') ) e.Replacement = 'UInvisibility';
else if ( (e.Replacee == 'Infrared') || (e.Replacee == 'ArtiTorch') ) e.Replacement = 'UFlashlight';
else if ( e.Replacee == 'RadSuit' ) e.Replacement = 'UJumpBoots';
else if ( e.Replacee == 'ArtiFly' ) e.Replacement = 'UJumpBoots';
else if ( (e.Replacee == 'Backpack') || (e.Replacee == 'BagOfHolding') ) e.Replacement = 'UnrealBackpack';
else if ( (e.Replacee == 'ArmorBonus') || (e.Replacee == 'ArtiTimeBomb') )
else if ( (e.Replacee == 'ArtiFly') || (e.Replacee == 'ArtiSpeedBoots') ) e.Replacement = 'UJumpBoots';
else if ( (e.Replacee == 'Backpack') || (e.Replacee == 'BagOfHolding') || (e.Replacee == 'ArtiHealingRadius') ) e.Replacement = 'UnrealBackpack';
else if ( (e.Replacee == 'ArmorBonus') || (e.Replacee == 'ArtiTimeBomb') || (e.Replacee is 'ArtiPoisonBag') || (e.Replacee is 'ArtiBlastRadius') )
{
if ( sting_abonus && Random[Replacements](0,3) ) e.Replacement = 'UArmorBonus';
else e.Replacement = 'Flare';
}
else if ( (e.Replacee == 'HealthBonus') || (e.Replacee == 'CrystalVial') ) e.Replacement = 'Bandages';
else if ( (e.Replacee == 'GreenArmor') || (e.Replacee == 'Silvershield') ) e.Replacement = 'KevlarSuit';
else if ( (e.Replacee == 'BlueArmor') || (e.Replacee == 'EnchantedShield') ) e.Replacement = 'UArmor';
else if ( (e.Replacee == 'GreenArmor') || (e.Replacee == 'Silvershield') || (e.Replacee == 'PlatinumHelm') ) e.Replacement = 'KevlarSuit';
else if ( (e.Replacee == 'BlueArmor') || (e.Replacee == 'EnchantedShield') || (e.Replacee == 'MeshArmor') ) e.Replacement = 'UArmor';
else if ( e.Replacee == 'AmuletOfWarding' ) e.Replacement = 'AsbestosSuit';
else if ( e.Replacee == 'FalconShield' ) e.Replacement = 'ToxinSuit';
else if ( (e.Replacee == 'Stimpack') || (e.Replacee == 'ArtiHealth') )
{
if ( Random[Replacements](0,1) ) e.Replacement = 'UHealth';
@ -1175,7 +1243,7 @@ Class UnrealMainHandler : EventHandler
else e.Replacement = 'Seeds';
}
else if ( e.Replacee == 'Medikit' ) e.Replacement = 'UHealth';
else if ( e.Replacee == 'ArtiTeleport' )
else if ( (e.Replacee == 'ArtiTeleport') || (e.Replacee == 'ArtiTeleportOther') || (e.Replacee == 'ArtiDarkServant') )
{
// I have no idea what to replace this with, so just have some random stuff
switch( Random[Replacements](0,sting_proto?7:5) )
@ -1207,6 +1275,40 @@ Class UnrealMainHandler : EventHandler
}
}
else if ( e.Replacee == 'TeleportFog' ) e.Replacement = 'UTeleportFog';
// Doomreal's weapon progression for Hexen is a bit more... involved when it comes to including proto content
else if ( (e.Replacee == 'FWeapFist') || (e.Replacee == 'CWeapMace') || (e.Replacee == 'MWeapWand') )
e.Replacement = 'DispersionPistol';
else if ( e.Replacee == 'FWeapAxe' ) e.Replacement = EitherOr('Automag','Betamag',sting_proto);
else if ( e.Replacee == 'CWeapStaff' ) e.Replacement = EitherOr('Stinger','Quadshot',sting_proto);
else if ( e.Replacee == 'MWeapFrost' ) e.Replacement = EitherOr('ASMD','Stunner',sting_proto);
else if ( (e.Replacee == 'FWeaponPiece3') || (e.Replacee == 'FWeapQuietus') || (e.Replacee.GetClassName() == 'mkFullQuietus') ) e.Replacement = 'Eightball';
else if ( e.Replacee == 'CWeaponPiece3' ) e.Replacement = 'WeaponPowerUp';
else if ( e.Replacee == 'MWeaponPiece3' ) e.Replacement = EitherOr('Automag','Betamag',sting_proto);
else if ( e.Replacee == 'FWeapHammer' ) e.Replacement = EitherOr('UFlakCannon','FlameGun',sting_proto);
else if ( e.Replacee == 'CWeapFlame' ) e.Replacement = EitherOr('Razorjack','UFlamethrower',sting_proto);
else if ( e.Replacee == 'MWeapLightning' ) e.Replacement = EitherOr('UBioRifle','Impaler',sting_proto);
else if ( e.Replacee == 'FWeaponPiece2' )
{
if ( sting_proto && sting_dubious ) e.Replacement = 'Bonesaw';
else e.Replacement = 'WeaponPowerUp';
}
else if ( (e.Replacee == 'CWeaponPiece2') || (e.Replacee == 'CWeapWraithverge') || (e.Replacee.GetClassName() == 'mkFullWraithverge') ) e.Replacement = 'URifle';
else if ( e.Replacee == 'MWeaponPiece2' ) e.Replacement = 'WeaponPowerUp';
else if ( e.Replacee == 'FWeaponPiece1' )
{
if ( sting_proto && sting_dubious ) e.Replacement = 'BigGun';
else e.Replacement = 'UnrealBackpack';
}
else if ( e.Replacee == 'CWeaponPiece1' )
{
if ( sting_proto && sting_dubious ) e.Replacement = 'SMiniGun';
else e.Replacement = 'UnrealBackpack';
}
else if ( (e.Replacee == 'MWeaponPiece1') || (e.Replacee == 'MWeapBloodscourge') || (e.Replacee.GetClassName() == 'mkFullBloodscourge') )
{
if ( sting_olsmp ) e.Replacement = 'OLSMP';
else e.Replacement = 'UnrealBackpack';
}
// replace UT items (prevents them from being cheated in)
else if ( e.Replacee is 'ImpactHammer' ) e.Replacement = 'DispersionPistol';
else if ( e.Replacee is 'Translocator' ) e.Replacement = 'UTranslocator';
@ -1252,7 +1354,7 @@ Class UnrealMainHandler : EventHandler
else if ( e.Replacee is 'UTHealthPack' ) e.Replacement = 'SuperHealth';
else if ( e.Replacee is 'UTHealthBonus' ) e.Replacement = 'Bandages';
else if ( e.Replacee is 'UTJumpBoots' ) e.Replacement = 'UJumpBoots';
else if ( e.Replacee is 'UTActivatable' ) e.Replacement = 'UNothing';
else if ( (e.Replacee is 'UTActivatable') && (!(e.Replacee is 'ActUTFullAmmoBox') || !(gameinfo.gametype&GAME_Hexen)) ) e.Replacement = 'UNothing';
else if ( e.Replacee is 'UTActivatableHealth' ) e.Replacement = 'UNothing';
}

View file

@ -593,7 +593,39 @@ Class UnrealHUD : BaseStatusBar
private void DrawKeys( double x, double y, bool leftright = false )
{
if ( deathmatch ) return; // no need to draw in DM
if ( gameinfo.gametype&(GAME_Hexen|GAME_Strife) ) return; // no key display for these ATM (will do eventually)
if ( gameinfo.gametype&(GAME_Hexen|GAME_Strife) )
{
if ( !automapactive ) return;
int kw = (gameinfo.gametype&GAME_Strife)?20:30,
kh = (gameinfo.gametype&GAME_Strife)?20:40;
int nkeys = 0;
Array<int> rows;
Array<Inventory> keys;
keys.Clear();
rows.Clear();
rows.Push(0);
for ( Inventory i=CPlayer.mo.inv; i; i=i.inv )
{
if ( !(i is 'Key') ) continue;
keys.Push(i);
if ( rows[rows.Size()-1] >= 6 ) rows.Push(1);
else rows[rows.Size()-1]++;
}
int j = 0;
CurX = (ClipX-kw);
for ( int i=0; i<rows.Size(); i++ )
{
CurY = (ClipY-rows[i]*kh)*0.5;
for ( int k=0; k<rows[i]; k++ )
{
Screen.DrawTexture(keys[j].Icon,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
j++;
CurY += kh;
}
CurX -= kw;
}
return;
}
CurX = x;
CurY = y;
int cnt = 0;
@ -768,11 +800,15 @@ Class UnrealHUD : BaseStatusBar
DrawString(mOldDigitsSmall,FormatNumber(sec,3),(633,378),DI_TEXT_ALIGN_RIGHT);
if ( sec2 != -1 )
DrawString(mOldDigitsSmall,FormatNumber(sec2,3),(556,378),DI_TEXT_ALIGN_LEFT);
if ( gameinfo.gametype&(GAME_Hexen|GAME_Strife) ) DrawKeys(0,0);
else
{
for ( int i=0; i<6; i++ )
{
if ( !CPlayer.mo.CheckKeys(i+1,false,true) ) continue;
DrawImage(OldKeys[((i==0)&&(gameinfo.gametype&GAME_Heretic))?6:i],(keyofs[i],366),DI_ITEM_OFFSETS);
}
}
if ( HudMode > 5 ) return;
// Draw frags in DM
if ( deathmatch ) DrawFragCount(ClipX-32,0);