PDA

View Full Version : Fake Duel script?


Masterkyle
11-18-2007, 01:56 AM
Can anyone tell me how to setup a fake duel like on duxon?
i cant tear apart the script on duxon to see how it works.
thanks

stoffe
11-18-2007, 08:06 AM
Can anyone tell me how to setup a fake duel like on duxon?
i cant tear apart the script on duxon to see how it works.
thanks

A duel circle fight is controlled by a number of scripts that set up the fight and end it when either combatant is defeated. Here is a rather simple example of how one might be done, it should hopefully give you a general idea of how it works.

This example requires two global number variables named "DuelPartyMember1" and "DuelPartyMember2" that must be added to the globalcat.2da file to keep track of who was in the party before the duel. It also needs two waypoints placed in the area with the tags PlayerDuelWaypoint and EnemyDuelWaypoint, which tell the position and orientation of the player and NPC combatand at the start of the fight.

First, the script that starts the duel. This moves the combatants into place, sets up match conditions, removes party members and starts the fighting. It would usually be run on the final node of a dialog that starts the duel:

// st_duelstart.nss
//
// Assumptions/Requirements:
// 1) Two waypoints are placed in the area at the positions where the player and opponent
// combatant are going to start out, with the tags "PlayerDuelWaypoint" and "EnemyDuelWaypoint"
//
// 2) Two global number variables named "DuelPartyMember1" and "DuelPartyMember2" must be added
// to the "globalcat.2da" file.

#include "k_inc_glob_party"

void ST_JumpFace(object oWP);
void ST_ClearParty();

void main() {
object oPlayerWP = GetObjectByTag("PlayerDuelWaypoint");
object oEnemyWP = GetObjectByTag("EnemyDuelWaypoint");
object oPlayer = GetFirstPC();
object oEnemy = GetObjectByTag("EnemyTag");

// Remove any party members currently with the player
ST_ClearParty();

// Set duel restrictions, may only use weapon with tag 'pl_sword' and
// forearm shields, but no other items, weapons or force powers.
SetForfeitConditions( FORFEIT_DXUN_SWORD_ONLY | FORFEIT_NO_FORCE_POWERS | FORFEIT_NO_ITEM_BUT_SHIELD );

// Jump player and combatant to their starting positions
AssignCommand(oPlayer, ST_JumpFace(oPlayerWP));
AssignCommand(oEnemy, ST_JumpFace(oEnemyWP));

// Make sure player and combatant are at full health
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(GetMaxHitPoints(oPlayer)), oPlayer);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(GetMaxHitPoints(oEnemy)), oEnemy);

// Make sure the player can't kill the opponent
SetMinOneHP(oEnemy, TRUE);

// Make the opponent hostile and start fighting.
ChangeToStandardFaction(oEnemy, STANDARD_FACTION_HOSTILE_1);
ExecuteScript("k_ai_master", oEnemy, 1003);
}


void ST_JumpFace(object oWP) {
JumpToObject(oWP);
SetFacing(GetFacing(oWP));
}


void ST_ClearParty() {
int iParty;
int iActive1 = -1;
int iActive2 = -1;

for (iParty = NPC_ATTON; iParty <= NPC_DISCIPLE; iParty++) {
if (IsNPCPartyMember(iParty)) {
if (iActive1 == -1)
iActive1 = iParty;
else
iActive2 = iParty;

RemovePartyMember(iParty);

object oNPC = GetObjectByTag(GetNPCTag(iParty));
ChangeToStandardFaction(oNPC, STANDARD_FACTION_NEUTRAL);
}
}

// These Global Number variables must be added to globalcat.2da
SetGlobalNumber("DuelPartyMember1", iActive1);
SetGlobalNumber("DuelPartyMember2", iActive2);
}

The forfeit conditions set in this script will handle special restrictions set on the fight, like the player not being allowed to use weapons, armor, inventory items etc. You can use any of the FORFEIT_ constants listed in nwscript.nss to add restrictions to a duel.


Next we have three scripts that determine if victory/loss conditions of the duel has been met. One that determines if the player has been cheating (using weapons that aren't allowed for example), one that checks if the player has been beaten and one that checks if the NPC has been beaten.

First the one that enforces the duel rules. This needs to be set as OnUserDefined event script of the area where the duel takes place (this is set in the .ARE file of the area):

// st_dueludef.nss
// NOTE: This should be placed as UserDefined event script of the AREA the duel
// takes place in.

void main() {
if (GetUserDefinedEventNumber() == 4001) {
ExecuteScript("st_duelend", GetArea(GetFirstPC()), GetLastForfeitViolation());
}

}

If forfeit conditions have been set the game will automatically signal user defined event number 4001 to the area when one of the conditions are met.


The next script checks if the player has been beaten. Since players may have insane health regeneration in this game it's not reliable to check the player's health total. Instead we look for when the player is killed, in which case the player will be immediately resurrected, healed a bit and the duel ends in loss. This script must be set as OnPlayerDeath event script in the module the duel takes place in (this is set in the module.ifo file):

// st_dueldeath.nss
// NOTE: This script must be set as OnPlayerDeath script in the module the
// duel will take place in.

void ST_PartialHeal(object oTarget, float fHealPercent=1.0, int bRes=TRUE);


void main() {
// The player died! Revive them somewhat bruised, and end the match.
ST_PartialHeal(GetLastPlayerDied(), 0.25);
ExecuteScript("st_duelend", GetArea(GetFirstPC()), 201);
}





void ST_RemoveHarmfulEffects(object oTarget=OBJECT_SELF) {
effect eEff = GetFirstEffect(oTarget);
int nType;

while (GetIsEffectValid(eEff)) {
nType = GetEffectType(eEff);
if ((nType == EFFECT_TYPE_POISON)
|| (nType == EFFECT_TYPE_PARALYZE)
|| (nType == EFFECT_TYPE_STUNNED)
|| (nType == EFFECT_TYPE_FRIGHTENED)
|| (nType == EFFECT_TYPE_SLEEP)
|| (nType == EFFECT_TYPE_ABILITY_DECREASE)
|| (nType == EFFECT_TYPE_ATTACK_DECREASE)
|| (nType == EFFECT_TYPE_AC_DECREASE)
|| (nType == EFFECT_TYPE_MOVEMENT_SPEED_DECREASE)
|| (nType == EFFECT_TYPE_SAVING_THROW_DECREASE)
|| (nType == EFFECT_TYPE_DAMAGE_DECREASE)
|| (nType == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE)
|| (nType == EFFECT_TYPE_FORCE_RESISTANCE_DECREASE)
|| (nType == EFFECT_TYPE_SKILL_DECREASE)
|| (nType == EFFECT_TYPE_BLINDNESS)
|| (nType == EFFECT_TYPE_ENTANGLE)
|| (nType == EFFECT_TYPE_CONFUSED)
|| (nType == EFFECT_TYPE_DROID_CONFUSED)
|| (nType == EFFECT_TYPE_DROIDSCRAMBLE)
|| (nType == EFFECT_TYPE_MINDTRICK))
{
DelayCommand(0.1, RemoveEffect(oTarget, eEff));
}
eEff = GetNextEffect(oTarget);
}
}


void ST_PartialHeal(object oTarget, float fHealPercent=1.0, int bRes=TRUE) {
if (bRes)
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), oTarget);

int iHeal = FloatToInt(IntToFloat(GetMaxHitPoints(oTarget)) * fHealPercent);
int iForce = FloatToInt(IntToFloat(GetMaxForcePoints(oTarget)) * fHealPercent);

ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(iHeal), oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHealForcePoints(iForce), oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HEAL), oTarget);

ST_RemoveHarmfulEffects(oTarget);
}



And finally we need to check for when the NPC loses the fight. Here we end the duel in player victory if the NPC is reduced to 1 hitpoints. This script needs to be set as OnDamaged event script of the opponent NPC combatant (in their .UTC file):

// st_dueldamaged.nss
// NOTE: This script must be set as OnDamaged event script on the combatant
// NPC the player fights a duel against.


void main() {
// The NPC is knocked down to 1 health, end the duel with player victory.
if ( GetCurrentHitPoints(OBJECT_SELF) <= 1 ) {
ExecuteScript("st_duelend", GetArea(GetFirstPC()), 200);
}
else {
ExecuteScript("k_ai_master", OBJECT_SELF, 1006);
}
}


All these three scripts fire the same script which handles the actual ending of the duel, which in this example is called st_duelend.nss. This script would look like:

// st_duelend.nss

#include "k_inc_glob_party"

void ST_EndDuel();

void main() {
int iParam = GetRunScriptVar();

switch (iParam) {
case FORFEIT_NO_FORCE_POWERS:
case FORFEIT_NO_ITEMS:
case FORFEIT_NO_WEAPONS:
case FORFEIT_DXUN_SWORD_ONLY:
case FORFEIT_NO_ARMOR:
case FORFEIT_NO_RANGED:
case FORFEIT_NO_LIGHTSABER:
case FORFEIT_NO_ITEM_BUT_SHIELD:
SendMessageToPC(GetFirstPC(), "You have violated the rules of the fight! You lose!");
ST_EndDuel();
break;

case 200:
SendMessageToPC(GetFirstPC(), "You are victorious!");
GiveGoldToCreature(GetFirstPC(), 1000);
ST_EndDuel();
break;

case 201:
SendMessageToPC(GetFirstPC(), "You have been defeated!");
ST_EndDuel();
break;

}
}


void ST_EndDuel() {
object oPlayer = GetFirstPC();
object oEnemy = GetObjectByTag("EnemyTag");
int iNPC1 = GetGlobalNumber("DuelPartyMember1");
int iNPC2 = GetGlobalNumber("DuelPartyMember2");

// Clear forfeit flags.
SetForfeitConditions(0);

// Make the combatants stop fighting
NoClicksFor(1.0);
AssignCommand(oEnemy, SurrenderToEnemies());
ChangeToStandardFaction(oEnemy, STANDARD_FACTION_NEUTRAL);
AssignCommand(oEnemy, ClearAllActions());
AssignCommand(oPlayer, ClearAllActions());
CancelCombat(oEnemy);
CancelCombat(oPlayer);

// Add back the party members the player had before the duel.
if (iNPC1 != -1)
AddPartyMember(iNPC1, GetObjectByTag(GetNPCTag(iNPC1)));

if (iNPC2 != -1)
AddPartyMember(iNPC2, GetObjectByTag(GetNPCTag(iNPC2)));
}



This script checks whether the fight ended in player victory or loss (depending on which of the other scripts where firing it), resets the duel, adds back the party members to the player's party and rewards the player with 1000 credits if they won.



(The Fine Print: This particular example is untested since I just wrote it, but barring any mistakes I've made it should work :))

Masterkyle
11-18-2007, 06:46 PM
I'm sorry if i confused you. I dont mean a duel betwen the player and npc. I mean a constant duel a fake duel between 2 npcs that keeps going.