[Logo]
 
  [Search] Search   [Recent Topics] Recent Topics   [Members]  Member Listing   [Groups] Back to home page 
[Register] Register / 
[Login] Login 
New/Modified Weapon Modifiers  XML
Forum Index -> Druids RPG
Author Message
Wail

Rampage

Joined: 09/20/2007 21:14:41
Messages: 183
Offline

Have started to get back into UT2004 stuff, and I decided to get back to one of the projects which I had started but wasn't fully completed. Looking for a bit of feedback and a critical eye, although not necessarily approval - These are ideas I'm planning for a DruidsRPG add-on, although I'm open to incorporating them into DruidsRPG if well received.


RW_DWVorpal
Summary: Allows creatures to ignore the Vorpal instant-kill effect if they have a certain property set.

Code:
class RW_DWVorpal extends RW_Vorpal
 	HideDropDown
 	CacheExempt
 	config(DWRPG);
 
 function AdjustTargetDamage(out int Damage, Actor Victim, Vector HitLocation, out Vector Momentum, class<DamageType> DamageType)
 {
 	local int Chance, i;
 	local Actor A;
 
 	for(i = 0; i < IgnoreDamageTypes.length; i++)
 		if(DamageType == IgnoreDamageTypes[i])
 			return; //hack to work around vorpal redeemer exploit.
 	
 	//General Superweapon check
 	if (DamageType.bSuperWeapon)
 	   return;
 
 	if (!bIdentified)
 		Identify();
 
 	if(Victim == None)
 		return; //nothing to do
 
 	if(Damage > 0)
 	{
 		Damage = Max(1, Damage * (1.0 + DamageBonus * Modifier));
 		Momentum *= 1.0 + DamageBonus * Modifier;
 	}
 
 	Chance = Modifier - MinModifier;
 
 	if(Damage > 0 && Chance >= rand(99))
 	{
 
     //Spawn the vorpal effects at the gun
 		if(Victim != None && Victim.isA('Pawn'))
 		{
 			A = spawn(class'RocketExplosion',,, Instigator.Location);
 			if (A != None)
 			{
 				A.RemoteRole = ROLE_SimulatedProxy;
 				A.PlaySound(sound'WeaponSounds.Misc.instagib_rifleshot',,2.5*Instigator.TransientSoundVolume,,Instigator.TransientSoundRadius);
 			}
 			
 			//If we hit an EnhancedMonster we may have Vorpal resistance
 			if (EnhancedMonster(Victim) != none)
 			{
 			   // If the monster's not immune to vorpals, and we randomly get a result higher than the monster's vorpal negation chance, then we vorpal
 			   if ( !EnhancedMonster(Victim).bVorpalImmune && EnhancedMonster(Victim).VorpalNegationChance < frand() )
          {
             Pawn(Victim).Died(Instigator.Controller, DamageType, Victim.Location);
             
             A = spawn(class'RocketExplosion',,, Victim.Location);
 				    if (A != None)
 				    {
 					     A.RemoteRole = ROLE_SimulatedProxy;
 					     A.PlaySound(sound'WeaponSounds.Misc.instagib_rifleshot',,2.5*Victim.TransientSoundVolume,,Victim.TransientSoundRadius);
 				    }
          }
          else //Spawn some effects to let us know the creature resisted our Vorpal
          {
             A = spawn(class'FX_BallTurret_Shield',,, Victim.Location);
          }
       }
       else //We hit a non EnhancedMonster, so we instantly kill it
       {
          Pawn(Victim).Died(Instigator.Controller, DamageType, Victim.Location);
 
 			   //Spawn the vorpal effects at the monster
          if(Victim != None)
 			   {
 				   A = spawn(class'RocketExplosion',,, Victim.Location);
 
 				   if (A != None)
 				   {
 					   A.RemoteRole = ROLE_SimulatedProxy;
 					   A.PlaySound(sound'WeaponSounds.Misc.instagib_rifleshot',,2.5*Victim.TransientSoundVolume,,Victim.TransientSoundRadius);
 				   }
 			   }
 			}
 
 		}
 	}
 }
 
 defaultproperties
 {
      ModifierOverlay=Shader'XGameShaders.BRShaders.BombIconYS'
 }
 



RW_DWEnergy
Summary: Alteration to the Energy weapon that allows creatures to scale the amount of energy leeched, to burn adrenaline from anyone attempting to leech from the creature, or to burn health from anyone attempting to leech from the creature.
Code:
class RW_DWEnergy extends RPGWeapon
 	HideDropDown
 	CacheExempt
   config(DWRPG);
 
 var config float DamageBonus;
 
 
 function AdjustTargetDamage(out int Damage, Actor Victim, Vector HitLocation, out Vector Momentum, class<DamageType> DamageType)
 {
   local float AdrenalineBonus;
   local float TempHealthSearingScaling;
 
 	if (!bIdentified)
 		Identify();
 
   if(Damage > 0)
 	{
 		Damage = Max(1, Damage * (1.0 + DamageBonus * Modifier));
 		Momentum *= 1.0 + DamageBonus * Modifier;
 	}
 
 	if (Pawn(Victim) == None)
 		return;
 
   //Calculate the Adrenaline bonus for this hit.
   if (Damage > Pawn(Victim).Health)
 		 AdrenalineBonus = Pawn(Victim).Health;
   else
 		 AdrenalineBonus = Damage;
   AdrenalineBonus *= 0.02 * Modifier;
 
   //If our victim is an EnhancedMonster, check certain properties that may affect the leeching process.
 	if (EnhancedMonster(Victim) != None)
   {
 	   //Scale the bonus for monsters less/more vulnerable to leeching
      if (EnhancedMonster(Victim).bEnergyLeechScaling)
         AdrenalineBonus*EnhancedMonster(Victim).EnergyLeechScaling;
 
      //Turn the bonus negative (and scale) for monsters which burn energy when leeched
      if (EnhancedMonster(Victim).bEnergySearingEnergyLeech)
      {
         AdrenalineBonus *= -1 * EnhancedMonster(Victim).EnergySearingScaling;
 	      Instigator.Controller.Adrenaline = FMin(Instigator.Controller.Adrenaline + AdrenalineBonus, Instigator.Controller.AdrenalineMax);
      }
 
      //Deal damage to the leecher for monsters which burn health when leeched
      if (EnhancedMonster(Victim).bHealthSearingEnergyLeech)
      {
         //If we are also an EnergySearingEnergyLeech monster, we need to take into account that the AdrenalineBonus is now negative.
         if (EnhancedMonster(Victim).bEnergySearingEnergyLeech)
            TempHealthSearingScaling = -1 * EnhancedMonster(Victim).HealthSearingScaling;
 
         Instigator.TakeDamage( (AdrenalineBonus*TempHealthSearingScaling), Victim, Instigator.Location, vect(0,0,0), vect(0,0,0), EnhancedMonster(Victim).HealthSearingDamageType);
      }
 
      //Perform normal energy leech effect
      //Under normal circumstances this should always evaluate true (bNoEnergyLeech = false). bNoEnergyLeech should only be true when bEnergySearing/HealthSearing are true to prevent standard EnergyLeeching from occurring after the searing effect.
      if (!EnhancedMonster(Victim).bNoEnergyLeech)
      {
         if ( UnrealPlayer(Instigator.Controller) != None && Instigator.Controller.Adrenaline < Instigator.Controller.AdrenalineMax
 	      && Instigator.Controller.Adrenaline + AdrenalineBonus >= Instigator.Controller.AdrenalineMax && !Instigator.InCurrentCombo() )
 		       UnrealPlayer(Instigator.Controller).ClientDelayedAnnouncementNamed('Adrenalin', 15);
 	      Instigator.Controller.Adrenaline = FMin(Instigator.Controller.Adrenaline + AdrenalineBonus, Instigator.Controller.AdrenalineMax);
      }
 
   }
   else //We are not affecting an EnhancedMonster, so proceed with the normal operations for standard Monsters.
   {
 	   if ( UnrealPlayer(Instigator.Controller) != None && Instigator.Controller.Adrenaline < Instigator.Controller.AdrenalineMax
 	   && Instigator.Controller.Adrenaline + AdrenalineBonus >= Instigator.Controller.AdrenalineMax && !Instigator.InCurrentCombo() )
 		    UnrealPlayer(Instigator.Controller).ClientDelayedAnnouncementNamed('Adrenalin', 15);
 	   Instigator.Controller.Adrenaline = FMin(Instigator.Controller.Adrenaline + AdrenalineBonus, Instigator.Controller.AdrenalineMax);
   }
 }
 
 defaultproperties
 {
      DamageBonus=0.030000
      ModifierOverlay=Shader'XGameShaders.PlayerShaders.LightningHit'
      MinModifier=-2
      MaxModifier=3
      AIRatingBonus=0.020000
      PostfixPos=" of Energy"
      PrefixNeg="Draining "
 }


Have a couple more in the works that I will post once they are more complete...
Wail

Rampage

Joined: 09/20/2007 21:14:41
Messages: 183
Offline

Two new-ish ones...

RW_DWManaShield
When the player holding this weapon takes damage, the damage first goes to their adrenaline before their health. Modifier determines the ratio of adrenaline to health points.
Code:
class RW_DWManaShield extends OneDropRPGWeapon
 	HideDropDown
 	CacheExempt
 	config(DWRPG);
 
 var config float DamageBonus;
 
 function AdjustPlayerDamage(out int Damage, Pawn InstigatedBy, Vector HitLocation, out Vector Momentum, class<DamageType> DamageType)
 {
 	local int TempDamage;
   local int TempAdrenaline;
   local int DifferenceAdrenaline;
   local int OwnerAdrenaline;
 
   if (!bIdentified)
 		Identify();
 
   if ( Pawn(Owner) != none && Pawn(Owner).Controller != none)
      OwnerAdrenaline = Pawn(Owner).Controller.Adrenaline;
 
 	if ( OwnerAdrenaline > 0 )
   {
      TempDamage = Damage - OwnerAdrenaline * (Modifier+1);                // 1 Mana Point negates Modifier+1 Damage Points
      TempAdrenaline = Max(0,OwnerAdrenaline - (Damage / (Modifier+1)));   // 1 Damage Point negates 1/Modifier+1 Mana Points
      DifferenceAdrenaline = -1 * (OwnerAdrenaline - TempAdrenaline);
 
      if (TempDamage > 0)
      {
         Damage = TempDamage;
         Pawn(Owner).Controller.AwardAdrenaline(DifferenceAdrenaline);
      }
      else
      {
         Damage = 0;
         Pawn(Owner).Controller.AwardAdrenaline(DifferenceAdrenaline);
      }
 
   }
 
   Super.AdjustPlayerDamage(Damage, InstigatedBy, HitLocation, Momentum, DamageType);
 }
 
 function AdjustTargetDamage(out int Damage, Actor Victim, Vector HitLocation, out Vector Momentum, class<DamageType> DamageType)
 {
 	if (!bIdentified)
 		Identify();
 
 	if(Damage > 0)
 	{
 		Damage = Max(1, Damage * (1.0 + DamageBonus * Modifier));
 		Momentum *= 1.0 + DamageBonus * Modifier;
 	}
 	super.AdjustTargetDamage(Damage, Victim, HitLocation, Momentum, DamageType);
 }
 
 defaultproperties
 {
      ModifierOverlay=Shader'XGameShaders.PlayerShaders.PlayerShieldSh'  //ChangeMe
      MinModifier=0
      MaxModifier=4
      bCanHaveZeroModifier=True
      DamageBonus=0.020000
      AIRatingBonus=0.040000
      PostfixPos=" of Mana Shield"
 }



RW_DWEarth
Combines 10% piercing effect with a weakened sturdy effect, and adds special resistance to Titan boulders.
Code:
class RW_DWEarth extends RPGWeapon
 	HideDropDown
 	CacheExempt
 	config(DWRPG);
 
 var config float DamageBonus;
 var class<DamageType> ModifiedDamageType;
 
 
 function float GetAIRating()
 {
 	if (Bot(Instigator.Controller) != None && Bot(Instigator.Controller).Enemy.ShieldStrength > 0)
 		return ModifiedWeapon.GetAIRating() + AIRatingBonus;
 
 	return ModifiedWeapon.GetAIRating();
 }
 
 
 function AdjustPlayerDamage(out int Damage, Pawn InstigatedBy, Vector HitLocation, out Vector Momentum, class<DamageType> DamageType)
 {
 	if (!bIdentified)
 		Identify();
 
 	//Reduce momentum, but not quite as well as a Sturdy Weapon
   if (Modifier > 0)
 	   Momentum = Momentum/Modifier*2;
   if (Modifier == 0)
      Momentum = Momentum/2;
   if (Modifier < 0)
      Momentum = Momentum*(Abs(Modifier)*2);
 
   //Resist Titan Rocks which do more than this threshold of damage
   if ( Modifier >= 0 && (ClassisChildOf(DamageType,class'DamTypeEarth') || DamageType == class'SMPDamTypeTitanRock') )
   {
      if (Damage > 2000)
         Damage = 2000 - Modifier * 100;
   }
 
 	Super.AdjustPlayerDamage(Damage, InstigatedBy, HitLocation, Momentum, DamageType);
 }
 
 
 function AdjustTargetDamage(out int Damage, Actor Victim, Vector HitLocation, out Vector Momentum, class<DamageType> DamageType)
 {
   local int TempDamage;
 
   if (!bIdentified)
 		 Identify();
 		 
 	if (Pawn(Victim) != None && Pawn(Victim).ShieldStrength > 0 && DamageType.default.bArmorStops)
 	{
      DamageType.default.bArmorStops = false;
 	   ModifiedDamageType = DamageType;
   }
 
   if(Damage > 0)
 	{
 	  //Retrieve 10% of the difference in damage caused by damage reduction
 		TempDamage = Max(Damage, OriginalDamage) - Min(Damage, OriginalDamage);
 		TempDamage /= 10;
 
     if (Modifier >= 0)
        Damage += TempDamage; //Add 10% of the damage difference (aka 10% piercing). See comments on RW_Piercing about this approach.
 
     Damage = Max(1, Damage * (1.0 + DamageBonus * Modifier));
 		Momentum *= 1.0 + DamageBonus * Modifier;
 	}
 }
 
 
 simulated function WeaponTick(float dt)
 {
 	if (ModifiedDamageType != None)
 	{
 		ModifiedDamageType.default.bArmorStops = true;
 		ModifiedDamageType = None;
 	}
 
 	Super.WeaponTick(dt);
 }
 
 
 defaultproperties
 {
      DamageBonus=0.040000
      ModifierOverlay=Shader'UT2004Weapons.Shaders.ShockHitShader' //Change Me
      MinModifier=-2
      MaxModifier=4
      PostfixPos=" of Earth"
      bCanHaveZeroModifier=True
      PrefixNeg="Stonecursed "
 }
 
Lad



Joined: 04/14/2008 19:13:31
Messages: 15
Location: Australia
Offline

Hey Wail I hope you don't mind but after I read your code for RW_DWManaShield, I was like And wanted to try it out. So I hope you don't mind that I compiled it to test it.

And it's completely awesome. You did a great job with it
Wail

Rampage

Joined: 09/20/2007 21:14:41
Messages: 183
Offline

Cool, thanks for the feedback Lad.
I may end up changing it in the future for balance purposes, as I'm not sure whether a linear increase is appropriate (consider a +8/+9 modifier!). But, then again, one rock would probably still do you in. Not at the balancing phase yet though.
Lad



Joined: 04/14/2008 19:13:31
Messages: 15
Location: Australia
Offline

Just one thing for when you do come to balance it. I know a lot of servers have an adren cap higher that 250, and I was testing it with a char that had 1000, and it was kinda impossible to die while I had the Mana Shield weapon out So you might have to bring in some crazy percentage formulas like default shield has? >.< Or just make it never stop 100% of the damage, just very close to?
Wail

Rampage

Joined: 09/20/2007 21:14:41
Messages: 183
Offline

Not sure how many DruidsRPG developers are still around here, but if there are any left I have a general question - Is there any particular reason why I wouldn't want to roll things like the Protection status (from RW_EnhancedProtection) into a superclass such as OneDropRPGWeapon?

It strikes me that a lot of interesting and cool effects are possible by using Inventory actors to designate effects, and then process them in the general superclass for all RPG weapons (nonmagical weapons wouldn't be affected -- but that's potentially justifiable). For example, one weapon could add a general ProtectionInv-style actor to allied players struck, protecting them from deadly hits. Another example could be a weapon which added a DamageBonusInv to every allied player within a certain radius every few seconds, boosting their damage.

The potential downside I see to this is that putting all of these inventory checks into a superclass is going to result in a lot more inventory checking, and it's going to happen with every weapon type. Currently it's pretty limited in scope to about four weapons and each only checks for one effect at a time. Any ideas on whether this would be problematic?
Szlat

Wicked Sick!

Joined: 05/18/2005 18:32:41
Messages: 2124
Location: UK
Offline

At the moment, the RW_EnhancedProtection only checks the inventory on the rare occasion when you are about to die. If you are intending to do 4 inventory checks everytime you fire a weapon and each time you take damage from a weapon, then that will add extra processing.

Would you have a super classed inventory item, with say AdjustTargetDamage and AdjustPlayerDamage functions? This would allow others to extend the concept.

But I can't tell you how much it will impact the performance. At least it is just server cpu, not network bandwidth. It will of course be affected by what the max weapon speed is on the servers. And how many other inventory items people have.

The alternative might be to do the checks less frequently - on weapon BringUp and PutDown, and perhaps just once a second, adding up the different bonuses into local variables stored in the OneDropWeapon or whatever superclass. So the weapon AdjustTargetDamage and AdjustPlayerDamage would just need to check the local variables. However, based on some of your earlier posts, I imagine you will want to adjust damage depending on what type of attack it is etc, so will want to processes each hit separately.
Wail

Rampage

Joined: 09/20/2007 21:14:41
Messages: 183
Offline

Another new modifier...


Code:
class RW_DWRetaliating extends OneDropRPGWeapon
 	HideDropDown
 	CacheExempt
   config(DWRPG);
   
 var config float DamageBonus;
 
 function AdjustPlayerDamage(out int Damage, Pawn InstigatedBy, Vector HitLocation, out Vector Momentum, class<DamageType> DamageType)
 {
 	local int TempDamage;
 
   if (!bIdentified)
 		Identify();
 
 	if (Pawn(Owner).Controller.bGodMode != true)
 	{
      if ( Monster(InstigatedBy) != none && InstigatedBy.GetTeamNum() != Pawn(Owner).GetTeamNum() && InstigatedBy != Pawn(Owner))       // Added check here to try and prevent the retaliation target from being the player
 	   {
         TempDamage = Damage * (1.5 + Modifier/2); //Simplified calculation here
         
         if (TempDamage > Modifier * 3000)
            TempDamage = Modifier * 3000;
 
         InstigatedBy.TakeDamage(TempDamage, Pawn(Owner), vect(0,0,0), vect(0,0,0), class'DamTypeRetaliation');
 	   }
 	}
 
   Super.AdjustPlayerDamage(Damage, InstigatedBy, HitLocation, Momentum, DamageType);
 }
 
 defaultproperties
 {
      ModifierOverlay=Shader'X_cp_fx.cp_lightpanner1'
      PostfixPos=" of Retaliation"
      bCanHaveZeroModifier=True
      MinModifier=0
      MaxModifier=4
      DamageBonus=0.03
 
      AIRatingBonus=0.0500000
 }



Currently we are running a couple of these new modifiers on DW's RPG Invasion server. The only remaining bug I'm aware of is that [occasionally?] when using a Retaliation weapon, some players have reported being instakilled by random hits -- Which suggests to me that the player is being set as the retaliation target for damage they are taking. I suspect this may happen if the monster that shot the projectiles died before the projectiles hit the player.
 
Forum Index -> Druids RPG
Go to: