Author |
Message |
![[Post New]](/dcforum/templates/default/images/icon_minipost_new.gif) 04/10/2008 20:58:01
|
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...
|
|
 |
![[Post New]](/dcforum/templates/default/images/icon_minipost_new.gif) 04/14/2008 01:55:46
|
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 "
}
|
|
 |
![[Post New]](/dcforum/templates/default/images/icon_minipost_new.gif) 04/14/2008 19:20:56
|
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
|
|
 |
![[Post New]](/dcforum/templates/default/images/icon_minipost_new.gif) 04/15/2008 11:14:36
|
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.
|
|
 |
![[Post New]](/dcforum/templates/default/images/icon_minipost_new.gif) 04/15/2008 19:04:37
|
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?
|
|
 |
![[Post New]](/dcforum/templates/default/images/icon_minipost_new.gif) 04/17/2008 13:56:00
|
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?
|
|
 |
![[Post New]](/dcforum/templates/default/images/icon_minipost_new.gif) 04/17/2008 16:02:10
|
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.
|
|
 |
![[Post New]](/dcforum/templates/default/images/icon_minipost_new.gif) 04/30/2008 14:30:15
|
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.
|
|
 |
|
|
|