Modifié par Lazarus Magni, 28 mars 2011 - 11:08 .
Are there any simple tutorials for how to modify spells, feats, and abilities for a PW?
#1
Posté 28 mars 2011 - 11:07
#2
Posté 28 mars 2011 - 11:36
1) find the spell script (see NWN wiki) and modify the spell behavior in it thats usefull for specific changes like that spell is not capped at lvl 20
2) spellhook, this will allow you to disable casting of the spell in certain area or lets say stacking AOEs or change the actual cast spell (wild magic etc.)
3) global changes in spells
this is the best way to make changes, but also most harder.
There is several ways how to make certain changes, you can modify some spells functions in include files like MySavingThrow or spellsIsTarget, but that won't allow you much. The way to do almost anything global is called "core function hook" see HERE.
And also Community Patch 1.70 allows to do this and more easily via changing the 70_inc_spells library. Because there is whole new spell engine in community patch and all spells are rewritten onto it, its possible to modify some basic spell informations like: caster level, DC or metamagic there.
Still both solutions needs to recompile all spell scripts after you make a change in any include file. To do this you need THIS. The Community Patch 1.70 has its own version in zip archive for builders.
I can show you examples with the community patch spell engine if you would consider this route (there are also spellscripts fixes in it). If you want to try the core function hook (which is needed if you would want to change other global things like: area of effect distance, spell damage type, etc.) tell me if you wouldn't understand it from my explanation in that document.
Modifié par ShaDoOoW, 28 mars 2011 - 11:40 .
#3
Posté 29 mars 2011 - 06:52
As to feats and abilities though, can any one provide me some information on this? Like say if I wanted to give the AA death arrow 3 uses per day instead of one, or alter the DD defensive stance to do something more usefull for a medium/high item magic world, like say perhaps have it double the DD DR, or give regen and SR or something (just random ideas, I would have to put more thought into it), does anyone know how to do that with out requiring a HAK? I see in the 2da I can modify certain things like requirements, but nothing along those lines. I know it can be done too, as we already have a number of these types of server side customizations.
Modifié par Lazarus Magni, 29 mars 2011 - 06:56 .
#4
Posté 29 mars 2011 - 07:25
Yea I forgot about fact that you can change some spell related informations in 2da like which class can cast it on what level.Lazarus Magni wrote...
Thanks for the response Shadow. I see that I can modify certain parameters for spells by either editing the 2da, or modifying the script in the toolset, so I think that may cover anything I might attempt with spells.
Though you already figured it, there is a good explanations of the fields in spells.2da - http://nwn.wikia.com/wiki/Spells.2da
But not all collumns are server-side, for example if you change targettype players wont be able to cast the spell at all.
As to feats and abilities though, can any one provide me some
information on this? Like say if I wanted to give the AA death arrow 3
uses per day instead of one
that could be done either via feat.2da and USESPERDAY collumn - see more here http://nwn.wikia.com/wiki/Feat.2da
or via feat script, you know feats that are not automatic actually triggers special non-player-castable spell which got script again, you can find the spellscript reference on wiki again. For Arrow of Death it is
X1_S2_DeathArrow.nss. So you could add there a code that increment feat use to 1 again unless it have been increased 3 times this rest already. etc.
bugged DD stance is special case, its hardcoded and there are only two ways how to alter is, one is using hak and creating a replacement for it and second is NWNX and some linux plugin.or alter the DD defensive stance to do
something more usefull for a medium/high item magic world, like say
perhaps have it double the DD DR, or give regen and SR or something
(just random ideas, I would have to put more thought into it), does
anyone know how to do that with out requiring a HAK? I see in the 2da I
can modify certain things like requirements, but nothing along those
lines. I know it can be done too, as we already have a number of these
types of server side customizations.
#5
Posté 30 mars 2011 - 07:12
Also is NWNX and the linux plugin the same thing needed to alter dev crit to say an increased multiplier? If so then I believe the servers to have that, since we already have that in place.
#6
Posté 30 mars 2011 - 07:36
Not really I tried to point out my knowledge here: http://social.biowar...-4407114-1.htmlLazarus Magni wrote...
Is there a list somewhere as to which columns in the 2dAs are server side?
That means you got nwnx_funcs, you need nwnx_events and UseFeat event. Since you got the NWNX installed it won't be problem to add this plugin, but even with that Im not totally sure this can "catch" the defensive stance being activated, cos im windows user.Also is NWNX and the linux plugin the same thing needed to alter dev crit to say an increased multiplier? If so then I believe the servers to have that, since we already have that in place.
#7
Posté 31 mars 2011 - 10:24
#8
Posté 06 juillet 2011 - 08:46
#9
Posté 07 juillet 2011 - 01:30
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, 8) == "!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
#10
Posté 07 juillet 2011 - 05:28





Retour en haut






