//:://///////////////////////////////////////////// //:: Default: On User Defined //:: NW_C2_DEFAULTD //:: Copyright (c) 2002 Bioware Corp. //::////////////////////////////////////////////// /* Determines the course of action to be taken on a user defined event. */ //::////////////////////////////////////////////// //:: Created By: Don Moar //:: Created On: April 28, 2002 //::////////////////////////////////////////////// //:: Updated By: Peter Westergaard //:: Updated For: Troll Regeneration //:: Updated On: Nov 7, 2002 //:: Based heavily on code written by //:: Magnifico Uno in Sept. 2002 //:: for Troll Regeneration //::////////////////////////////////////////////// #include "PW_INC_TROLL" void main() { // Declare important variables here. int nPermDamage; // The amount of non-regenerable damage the troll has suffered. int nTempDamage; // The amount of regenerable damage the troll has suffered object oTroll = OBJECT_SELF; object oKiller; // The creature who killed the troll. // Effects to be used in applying visual or other effects. effect eKO; effect eRes; effect eBurn; // enter desired behaviour here switch ( GetUserDefinedEventNumber () ) { case 1005: // Troll On-Physical Attack break; case 1006: // Troll On-Damage nPermDamage = CalculateTrollDamage(); // Function defined in pw_inc_troll break; case 1007: // Troll On-Death nPermDamage = CalculateTrollDamage(); // Function defined in pw_inc_troll nTempDamage = GetLocalInt( OBJECT_SELF, "nTempDamage" ); oKiller = GetLastKiller(); // Who killed the Troll? if (nPermDamage >= GetMaxHitPoints() ) // We have finally done true lethal damage to the troll. Destroy it. DestroyMe(); // Function defined in pw_inc_troll else { // Troll is likely to survive, if we get to this point in the script. // We have not done true lethal damage, but since we are running the // OnDeath event, it must have brought the troll's HP to zero or lower. // First Check: Is the troll already 'down'? if ( GetLocalInt( OBJECT_SELF, "bTrollDown" ) == TRUE ) { //Troll has already been knocked down (i.e. it is "dead-but-regenerating". // Did it take ANY fire damage this attack? If so, burn the troll. // (We can just finish it off quickly this way). if ( GetDamageDealtByType( DAMAGE_TYPE_FIRE ) > 0 ) { // Destroy the Troll outright. It's helpless and burning. DestroyMe(); return; } else if ( GetBaseItemType( GetItemInSlot( INVENTORY_SLOT_LEFTHAND, oKiller ) ) == BASE_ITEM_TORCH ) { // The PC had a torch equipped in their hand (either one). // Destroy the Troll outright. It's helpless and burning. // ---- // Originally, I had wanted to include this in the On Physical Attacked // event, and it would kill the troll, but not credit the killer with XP. // So I opted for this solution, which requires the torch-weilder to actually // KILL the Troll (and since it has 1HP, and is prone, this shouldn't be difficult). AssignCommand ( oKiller, ActionPlayAnimation ( ANIMATION_LOOPING_GET_LOW , 1.0 , 1.5 ) ); AssignCommand ( oKiller, ActionDoCommand ( AssignCommand ( oTroll, DestroyMe() ) ) ); // Perhaps there is a cleaner way to do this, but what I was // attempting to do above is to force the PC to kneel at the // troll's corpse as an action, then only when that action is // complete, force the PC to signal to the troll to destroy itself. // It works, even though that second command is a little odd to read. return; } else { // Else no fire damage was dealt, so troll stays down and still alive. // Since it took damage this turn, call the "Knockdown" UDE that // resurrects the troll and applies knockdown. This will prevent the // PC from 'killing' the troll with non-fire damage, since 'killing' // the troll leaves a corpse which cannot be interacted with. SignalEvent ( OBJECT_SELF, EventUserDefined (2400)); } } else { // Knock the troll down from a standing position (i.e the troll just received // damage which took it from positive HP to 0 or negative HP, but it has // not sustained 'lethal' damage yet. // We will 'simulate' the troll regeneration by repeatedly calling the // "pw_inc_healtroll" script, which adds 5 HP to the troll, and when it // reaches a positive HP total, resurrects and heals the troll. SignalEvent ( OBJECT_SELF, EventUserDefined (2400)); SetLocalInt( OBJECT_SELF, "bTrollDown", TRUE ); } // The troll has survived because not enough permanent damage was done // to the troll. The troll should already be looping through UDE 2401, // which handles regeneration. UDE 2401 is first called from within the // "CalculateDamage()" function defined in the include file. } break; case 2400: // Troll Knockdown - the troll has accumulated more than its MaxHP in damage. but it // is NOT dead at this point because enough of that damage is non-permanent (i.e. // regenerable - not fire or acid). Thus, we have to strip away the XP the Killer // and their faction was just awarded. RollbackPartyXP (); // Function defined in include file "pw_inc_troll". FloatingTextStringOnCreature ( "The Troll is not dead!", OBJECT_SELF, FALSE ); // Resurrect and Knockdown the Troll, so that it appears to "die" into a Knockdown pose. // If we put these same actions into the OnDeath script, they do not have any effect, but // here in a UDE called immediately from within the OnDeath script, they perform as we hope. eRes = EffectResurrection ( ); ApplyEffectToObject ( DURATION_TYPE_INSTANT , eRes, OBJECT_SELF ); eKO = EffectKnockdown ( ); ApplyEffectToObject ( DURATION_TYPE_PERMANENT , eKO, OBJECT_SELF ); break; case 2401: // Troll Regeneration - This UDE is called as soon as the first regenerable damage // is taken by the troll, (determined within the "CalculateDamage()" function defined // in the include file) and recursively calls itself until all regenerable damage // is healed. nPermDamage = GetLocalInt ( OBJECT_SELF, "nPermDamage" ); nTempDamage = GetLocalInt ( OBJECT_SELF, "nTempDamage" ); oKiller = GetLocalObject ( OBJECT_SELF, "oKiller" ); if ( nTempDamage > 0 ) { // Regenerate 5 HP, unless there are fewer than 5 "regenerable" hits left on // the troll! (In which case, just heal up what's remaining). int nHP = ( nTempDamage < 10 ) ? nTempDamage : 10 ; nTempDamage -= nHP; SetLocalInt ( OBJECT_SELF, "nTempDamage", nTempDamage ); // Sound effect of troll regenerating (one each depending if // troll is "dead" or still standing if (GetLocalInt (OBJECT_SELF, "bTrollDown") == TRUE) PlaySound("al_na_sludggrat2"); // Sound for dead troll regenerating else PlaySound("as_mg_telepin1"); // Sound for living troll regenerating if ( ( nTempDamage + nPermDamage ) < GetMaxHitPoints() && GetLocalInt( OBJECT_SELF, "bTrollDown" ) == TRUE ) { // The troll has just moved back into positive HP from negative. // So we need to resurrect and possibly heal up the troll a tiny bit. // Technically, instead of resurrection, we should be locating and // removing the Knockdown effect, but this code works as expected. // Perhaps resurrection or healing removes knockdown as a sideffect. effect eRes = EffectResurrection ( ); ApplyEffectToObject ( DURATION_TYPE_INSTANT , eRes, OBJECT_SELF ); effect eHeal = EffectHeal ( ( GetMaxHitPoints() - ( nTempDamage + nPermDamage ) ) - GetCurrentHitPoints() ); ApplyEffectToObject ( DURATION_TYPE_INSTANT , eHeal, OBJECT_SELF ); // Make the troll pursue its killer when it stands back up. ActionAttack ( oKiller ); // And of course, the troll isn't considered "down" any more. SetLocalInt( OBJECT_SELF, "bTrollDown", FALSE ); } else if ( GetLocalInt( OBJECT_SELF, "bTrollDown" ) == FALSE ) { // Troll is already standing, but needs to heal. Heal the troll by nHP hit points. effect eHeal = EffectHeal ( nHP ); ApplyEffectToObject ( DURATION_TYPE_INSTANT , eHeal, OBJECT_SELF ); } // DelayCommand( 6.0, ExecuteScript( "pw_inc_healtroll", OBJECT_SELF )); if ( nTempDamage > 0 ) // We need to continue regenerating, if there are additional non-permanent wounds, otherwise // we're all healed up and can stop recursing until we accumulate more temporary damage. DelayCommand( 6.0, SignalEvent (OBJECT_SELF, EventUserDefined(2401) ) ); } break; } return; }