Defensive Stance: x2_s2_defstance
Ki Crit has to be done in the engine, I THINK - can't check easily atm.
Most feats, spells, items, etc, can be hooked with nwnx_events. Here's our events script by way of comparison. We use it for all sorts of things - binding SIMTools commands to voicechats, instant-use items, fast actions/spells, and custom feats and skills:
//::////////////////////////////////////////////////////////////////////////:://
//:: SIMTools V3.0 Speech Integration & Management Tools Version 3.0 :://
//:: Created By: FunkySwerve :://
//:: Created On: April 4 2006 :://
//:: Last Updated: March 27 2007 :://
//:: With Thanks To: :://
//:: Dumbo - for his amazing plugin :://
//:: Virusman - for Linux versions, and for the reset plugin, and for :://
//:: his excellent events plugin, without which this update would not :://
//:: be possible :://
//:: Dazzle - for his script samples :://
//:: Butch - for the emote wand scripts :://
//:: The DMFI project - for the languages conversions and many of the emotes:://
//:: Lanessar and the players of the Myth Drannor PW - for the new languages:://
//:: The players and DMs of Higher Ground for their input and playtesting :://
//::////////////////////////////////////////////////////////////////////////:://
//This script is only used by Linux users, to tell what conversation node was selected in the popup menus.
//The other events shown will work with the Linux version but are commented out
//#include "aps_include"
//#include "nwnx_events"
#include "hg_inc"
#include "fky_chat_instant"
void main() {
int nEventType = GetEventType();
int nSubType;
string sCommand;
location lTarget;
object oTarget, oItem;
switch (nEventType) {
case EVENT_TYPE_CAST_SPELL:
SetActionMode(OBJECT_SELF, ACTION_MODE_COUNTERSPELL, FALSE);
nSubType = GetEventSubType();
// 0x08000000 = already an instant spell; 0x03000000 = last legit class slot
if (GetIsPC(OBJECT_SELF) && !(nSubType & 0x08000000) && (nSubType & 0x07000000) < 0x03000000) {
switch (nSubType & 0xFFFF) {
case SPELL_TRUE_STRIKE: /* don't let Nightblades cast True Strike swiftly when they go in */
case SPELL_LESSER_RESTORATION:
case SPELL_RESTORATION:
case HGSPELL_CRITICAL_STRIKE:
case HGSPELL_DOLOROUS_BLOW:
if (GetObjectType(GetEventTarget()) != OBJECT_TYPE_ITEM) {
SetLocalInt(OBJECT_SELF, "EventSpell", nSubType);
SetLocalObject(OBJECT_SELF, "EventTarget", GetEventTarget());
DelayCommand(0.0, ExecuteScript("ev_swiftspell", OBJECT_SELF));
BypassEvent();
}
break;
case SPELL_HOLD_PERSON:
if (GetclassByPosition(((nSubType >> 24) & 0x7) + 1, OBJECT_SELF) != class_TYPE_CLERIC)
break;
if (GetObjectType(GetEventTarget()) != OBJECT_TYPE_ITEM) {
SetLocalInt(OBJECT_SELF, "EventSpell", nSubType);
SetLocalObject(OBJECT_SELF, "EventTarget", GetEventTarget());
DelayCommand(0.0, ExecuteScript("ev_swiftspell", OBJECT_SELF));
BypassEvent();
}
break;
case HGSPELL_VOCALIZE:
if (1 || GetclassByPosition(((nSubType >> 24) & 0x7) + 1, OBJECT_SELF) != class_TYPE_WIZARD)
break;
if (GetObjectType(GetEventTarget()) != OBJECT_TYPE_ITEM) {
SetLocalInt(OBJECT_SELF, "EventSpell", nSubType);
SetLocalObject(OBJECT_SELF, "EventTarget", GetEventTarget());
DelayCommand(0.0, ExecuteScript("ev_swiftspell", OBJECT_SELF));
BypassEvent();
}
break;
}
}
break;
case EVENT_TYPE_USE_ITEM:
oItem = GetEventItem();
if (GetLocalInt(oItem, "FKY_CHAT_INSTANT")) {
oTarget = GetEventTarget();
if (GetObjectType(oTarget) == OBJECT_TYPE_TRIGGER)
lTarget = GetLocation(OBJECT_SELF);
else
lTarget = Location(GetArea(OBJECT_SELF), GetEventPosition(), GetFacing(OBJECT_SELF));
if (DoInstantUse(OBJECT_SELF, oItem, oTarget, lTarget))
BypassEvent();
}
break;
case EVENT_TYPE_USE_FEAT:
nSubType = GetEventSubType();
if (nSubType == FEAT_STUNNING_FIST && GetLLControlclass(OBJECT_SELF) == class_TYPE_MONK) {
SetLocalObject(OBJECT_SELF, "EventTarget", GetEventTarget());
DelayCommand(0.0, ExecuteScript("ev_stunningfist", OBJECT_SELF));
BypassEvent();
} else if (nSubType == FEAT_QUIVERING_PALM) {
SetLocalObject(OBJECT_SELF, "EventTarget", GetEventTarget());
DelayCommand(0.0, ExecuteScript("ev_quiveringpalm", OBJECT_SELF));
BypassEvent();
} else if (nSubType == FEAT_CALLED_SHOT &&
GetLevelByclass(class_TYPE_RANGER, OBJECT_SELF) >= 35 &&
GetHasFeat(FEAT_EPIC_BANE_OF_ENEMIES, OBJECT_SELF)) {
SetLocalObject(OBJECT_SELF, "EventTarget", GetEventTarget());
DelayCommand(0.0, ExecuteScript("ev_calledshot", OBJECT_SELF));
BypassEvent();
} else if (nSubType == FEAT_DISARM || nSubType == FEAT_IMPROVED_DISARM) {
SetLocalObject(OBJECT_SELF, "EventTarget", GetEventTarget());
DelayCommand(0.0, ExecuteScript("ev_disarm", OBJECT_SELF));
BypassEvent();
} else if (nSubType == FEAT_KNOCKDOWN || nSubType == FEAT_IMPROVED_KNOCKDOWN) {
SetLocalObject(OBJECT_SELF, "EventTarget", GetEventTarget());
DelayCommand(0.0, ExecuteScript("ev_knockdown", OBJECT_SELF));
BypassEvent();
} else if (FindSubString(" 304 305 335 336 337 338 339 340 341 342 872 873 898 900 901 902 903 1060 1061 ", " " + IntToString(nSubType) + " ") >= 0) {
if (GetHasEffectOfType(EFFECT_TYPE_POLYMORPH, OBJECT_SELF)) {
FloatingTextStringOnCreature("You cannot change shape while already polymorphed!", OBJECT_SELF, FALSE);
BypassEvent();
}
}
break;
case EVENT_TYPE_USE_SKILL:
nSubType = GetEventSubType();
if (nSubType == SKILL_TAUNT) {
SetLocalObject(OBJECT_SELF, "EventTarget", GetEventTarget());
DelayCommand(0.0, ExecuteScript("ev_taunt", OBJECT_SELF));
BypassEvent();
}
break;
case EVENT_TYPE_TOGGLE_MODE:
nSubType = GetEventSubType();
if (nSubType == ACTION_MODE_COUNTERSPELL) {
if (GetIsObjectValid(GetAttackTarget(OBJECT_SELF)))
ClearAllActions(TRUE);
RemoveEffectsOfType(EFFECT_TYPE_ETHEREAL, OBJECT_SELF);
}
break;
case EVENT_TYPE_PICKPOCKET:
oTarget = GetEventTarget();
if (GetIsPC(OBJECT_SELF) && GetIsPC(oTarget)) {
if (GetLocalInt(GetArea(OBJECT_SELF), "nopp")) {
FloatingTextStringOnCreature("You cannot pickpocket other players!", OBJECT_SELF, FALSE);
BypassEvent();
}
if (abs(GetHitDice(oTarget) - GetHitDice(OBJECT_SELF)) > 6) {
FloatingTextStringOnCreature("You cannot pickpocket players more than 6 levels above or below you!", OBJECT_SELF, FALSE);
BypassEvent();
}
if (GetIsHardcore(OBJECT_SELF) || GetIsHardcore(oTarget)) {
FloatingTextStringOnCreature("Hardcore players cannot pickpocket or be pickpocketed by other players!", OBJECT_SELF, FALSE);
BypassEvent();
}
}
RemoveEffectsOfType(EFFECT_TYPE_ETHEREAL, OBJECT_SELF);
break;
case EVENT_TYPE_QUICKCHAT:
nSubType = GetEventSubType();
sCommand = GetLocalString(OBJECT_SELF, "VoiceBind_" + IntToString(nSubType));
if (GetLocalString(OBJECT_SELF, "VoiceBind_Save") != "") {
sCommand = GetLocalString(OBJECT_SELF, "VoiceBind_Save");
DeleteLocalString(OBJECT_SELF, "VoiceBind_Save");
if (nSubType >= 100 ||
(nSubType >= VOICE_CHAT_ENEMIES && nSubType <= VOICE_CHAT_FLEE) ||
(nSubType >= VOICE_CHAT_LOOKHERE && nSubType <= VOICE_CHAT_TASKCOMPLETE) ||
(nSubType >= VOICE_CHAT_TALKTOME && nSubType <= VOICE_CHAT_BADIDEA)) {
if (GetStringLowerCase(sCommand) == "clear") {
DeleteLocalString(OBJECT_SELF, "VoiceBind_" + IntToString(nSubType));
DeletePersistentVariable(OBJECT_SELF, "VoiceBind_" + IntToString(nSubType));
FloatingTextStringOnCreature(COLOR_GREEN + "Voice chat cleared!", OBJECT_SELF, FALSE);
} else {
SetLocalString(OBJECT_SELF, "VoiceBind_" + IntToString(nSubType), sCommand);
SetPersistentString(OBJECT_SELF, "VoiceBind_" + IntToString(nSubType), sCommand);
FloatingTextStringOnCreature(COLOR_GREEN + "Voice chat bound!", OBJECT_SELF, FALSE);
}
} else
FloatingTextStringOnCreature(COLOR_RED + "You cannot bind that voice chat!", OBJECT_SELF, FALSE);
BypassEvent();
} else if (sCommand != "" || (nSubType >= 100 && nSubType <= 110)) {
if (sCommand == "") {
switch (nSubType) {
case 100: sCommand = "!autocast"; break;
case 101: sCommand = "!list imm"; break;
case 102: sCommand = "!effects"; break;
case 103: sCommand = "!who inparty class"; break;
case 104: sCommand = "!effects eq"; break;
case 105: sCommand = "!list servers"; break;
case 107: sCommand = "!who player class group=area"; break;
case 108: sCommand = "!list voicebinds"; break;
case 109: sCommand = "!render"; break;
case 110: sCommand = "!stuck"; break;
default: sCommand = "!time"; break;
}
}
if (GetStringLeft(sCommand, == "!target ") {
sCommand = GetSubString(sCommand, 8, 255);
DeleteLocalObject(OBJECT_SELF, "FKY_CHAT_TARGET");
} else {
SetLocalObject(OBJECT_SELF, "FKY_CHAT_TARGET", OBJECT_SELF);
SetLocalInt(OBJECT_SELF, "FKY_CHAT_TARGET_CLEANUP", 1);
}
AssignCommand(OBJECT_SELF, SpeakString(sCommand, TALKVOLUME_WHISPER));
BypassEvent();
}
break;
}
}
Funky