Yes, you can modify stuff like this. Some feats are already accessible through nwscript, like the PDK abilities added in 1.67. Others can only be hooked with nwnx_events. Here's our code for it, which handles all custom events (see the EVENT_TYPE_USE_FEAT partway down). This script bypasses the normal event, and fires our own custom script instead.
#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 || nSubType == HGFEAT_LEG_DISARM || nSubType == HGFEAT_PAR_DISARM) {
SetLocalObject(OBJECT_SELF, "EventTarget", GetEventTarget());
DelayCommand(0.0, ExecuteScript("ev_disarm", OBJECT_SELF));
BypassEvent();
} else if (nSubType == FEAT_KNOCKDOWN || nSubType == FEAT_IMPROVED_KNOCKDOWN || nSubType == HGFEAT_LEG_KNOCKDOWN || nSubType == HGFEAT_PAR_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;
}
}
If memory serves, defensive stance IS NOT directly accessible via nwscript - we made an item to fire our hgs_gen_damshld script which decrements its uses, instead of hooking it via nwnx_events. Here's the relevant section of code:
if (GetResRef(si.item) == "ca_dwd_defense") {
if (!GetHasFeat(FEAT_DWARVEN_DEFENDER_DEFENSIVE_STANCE, si.caster)) {
FloatingTextStringOnCreature("You have no uses of Defensive Stance remaining!", si.caster, FALSE);
SetItemSpellUses(si.item, 0);
return;
}
DecrementRemainingFeatUses(si.caster, FEAT_DWARVEN_DEFENDER_DEFENSIVE_STANCE);
SetItemSpellUses(si.item, GetRemainingFeatUses(si.caster, FEAT_DWARVEN_DEFENDER_DEFENSIVE_STANCE));
si.id = HGEFFECT_DEFENSIVE_WEAVE;
si.clevel = GetLevelIncludingLLs(class_TYPE_DWARVEN_DEFENDER, si.caster);
fDur = RoundsToSeconds(si.clevel * 2);
eLink = EffectDamageShield((si.clevel * 3) / 2, DAMAGE_BONUS_1d6, DAMAGE_TYPE_BLUDGEONING);
eLink = EffectLinkEffects(eLink, EffectVisualEffect(PRCVFX_DUR_STONE4));
eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE));
eLink = ExtraordinaryEffect(eLink);
SetEffectSpellId(eLink, si.id);
ApplyVisualToObject(VFX_IMP_DUST_EXPLOSION, si.caster);
}
...*snip*...
RemoveEffectsFromSpell(si.id, si.target);
SignalEvent(si.target, EventSpellCastAt(si.caster, si.id, FALSE));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, si.target, fDur);
Funky
Modifié par FunkySwerve, 24 décembre 2012 - 03:39 .