Everything following this sentence is a repost from one of my old weathersong posts, reformatted and updated where I noticed anachronisms.
///////////////////////////////////////////////////////
I'll happily share my anti-cheat code, though without a demo mod its a bit convoluted at best, and it requires includes from my legendary level system. On the upside, it is by far the most exacting cheat checker I've seen - it verifies every single feat, rather than counting them, using wrappers from the LL scripts to see if they meet the reqs for each feat. Another, even more secure option, would be the PRC's convo CC, which recreates the character serverside via a convo. That was overkill as far as I was concerned, however, since the best they can slip by mine is not much - just not enough incentive for most. Anyway, these scripts are placed in the Actions Takens lines of a convo that characters must complete in the starting area in order to get jumped to the module proper.
Here is a link to the dlg file via dropbox, for reference when reading this.In the first node (OWNER's) (script is fky_hakchk_start in demo conv):
#include "hgll_func_inc"
void main() {
object oPC = GetPCSpeaker();
struct xAbility ability;
struct xAbility base;
if (!GetIsObjectValid(GetItemPossessedBy(oPC, "PCList"))) {//GetXP(oPC) == 0)
ReplenishLimitedUseFeats(oPC);//in case they try to use the feat to dodge detection (unlikely, but whatever)
ability = GetRoughAbilities(oPC);//Pull up info on base skills and stats
base = GetBaseAbilities(ability, oPC);//Process that data further to get base skills and base stats
SetBaseAbilityMarkers(base, oPC);//Set local ints for the 6 ability scores and 27 skills
//we will use this data to verify that the characters feats and stats are legal
}
}
In the next eleven nodes (nodes 2 through 12), I use both OWNER's and PC's nodes to keep the convo shorter (script is fky_hakchk_feat in demo convo):
#include "hgll_func_inc"
int GetIsRacialFeat(int nFeat) {
if ((nFeat > 226) && (nFeat < 251))
return TRUE;
int nReturn = FALSE;
switch(nFeat) {
case 256:
case 258:
case 354:
case 375: nReturn = TRUE; break;
default : nReturn = FALSE; break;
}
return nReturn;
}
int GetIsDomainFeat(int nFeat) {
if ((nFeat > 305) && (nFeat < 326))
return TRUE;
return FALSE;
}
void DebugIt(string sIllegal) {
string sInsert = "Reason for feat failure = ";
sInsert = sInsert + sIllegal;
WriteTimestampedLogEntry(sInsert);
SendMessageToAllDMs(sInsert);
}
int GetIsMiscclassOrRaceFeat(int nFeat, object oPC) {
if (((nFeat == 1) || (nFeat == 41)) && GetclassByPosition(1, oPC) == class_TYPE_RANGER)
return TRUE;
if (((nFeat == 6) || (nFeat == 39)) && GetclassByPosition(1, oPC) == class_TYPE_MONK)
return TRUE;
if (nFeat == 170 && GetRacialType(oPC) == RACIAL_TYPE_GNOME)
return TRUE;
return FALSE;
}
int GetIsFeatLegal(int nFeat, object oPC, int nclass1) {
if (GetIsMiscclassOrRaceFeat(nFeat, oPC))
return TRUE;//covers feats given to classes or races regardless of requisites
if (GetIsFeatDevCrit(nFeat))
return FALSE;
if (!GetAreFeatStatReqsMet(nFeat, oPC)) {DebugIt("StatReq");
return FALSE;}
if (!GetAreFeatSkillReqsMet(nFeat, oPC)) {DebugIt("SkillReq");
return FALSE;}
if (!GetAreFeatFeatReqsMet(nFeat, oPC)) {DebugIt("FeatReq");
return FALSE;}
if (!GetHasRequiredSpellLevelForFeat(oPC, nFeat)) {
DebugIt("SpellLevReq");
return FALSE;
}
if (!GetIsclassFeat(nFeat, nclass1, oPC) &&
!GetIsRacialFeat(nFeat) &&
!GetIsDomainFeat(nFeat) &&
!GetIsGeneralFeat(nFeat)) {
DebugIt("Non-class/Gen");
return FALSE;//if it's not a class feat and it's not a general feat return FALSE
}
return TRUE;
}
void main() {
object oPC = GetPCSpeaker();
int nclass1 = GetclassByPosition(1, oPC);
int nTrack = GetLocalInt(oPC, "FeatCheckCount");//we save scripts by using the same one in all the nodes and incrementing this int to switch the feats checked
int nFeat;
string sIllegal;
int nStart = nTrack*100;
int nBusted = GetLocalInt(oPC, "Hacker");
if (!GetIsObjectValid(GetItemPossessedBy(oPC, "PCList"))) {//GetXP(oPC) == 0)
if (nTrack < 10) {//the feats below 1000
for(nFeat = nStart; nFeat < (nStart + 99); nFeat++) {//loop through the feat constants (out of 1072)
if (GetHasFeat(nFeat, oPC)) {//if the PC has the feat
if (!GetIsFeatLegal(nFeat, oPC, nclass1)) {
SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal feats
sIllegal = "Illegal Feat ("+ IntToString(nFeat) + ") Detected - Name: " + GetName(oPC) + "; Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
WriteTimestampedLogEntry(sIllegal);
SendMessageToAllDMs(sIllegal);
break;
}
}
}
} else {//feats from 1000 to 1088 - if the character breaks convo and restarts, some feats just checked again
for(nFeat = 1000; nFeat <= 1088; nFeat++) {//loop through the feat constants (out of 1088)
if (GetHasFeat(nFeat, oPC)) {//if the PC has the feat
if (!GetIsFeatLegal(nFeat, oPC, nclass1)) {
SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal feats
sIllegal = "Illegal Feat ("+ IntToString(nFeat) + ") Detected - Name: " + GetName(oPC) + "; Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
WriteTimestampedLogEntry(sIllegal);
SendMessageToAllDMs(sIllegal);
break;
}
}
}
}
}
nTrack++; //increment the tracker so next batch of ints checked next time
SetLocalInt(oPC, "FeatCheckCount", nTrack); //
}
Thats a loop that checks chunks of 100 feats each time, seperate to prevent TMIs.
In the next node (node 13) (script is fky_hakchk_stat):
#include "hg_inc"
#include "hgll_func_inc"
string GetBicFileName(object oPC) {
string sChar, sBicName;
string sPCName = GetStringLowerCase(GetName(oPC));
int i, iNameLength = GetStringLength(sPCName);
for(i=0; i < iNameLength; i++) {
sChar = GetSubString(sPCName, i, 1);
if (TestStringAgainstPattern("(*a|*n|*w|'|-|_)", sChar)) {
if (sChar != " ") sBicName += sChar;
}
}
return GetStringLeft(sBicName, 16);
}
int GetLegalHitPoints(object oPC) {
int nclass = GetclassByPosition(1, oPC);
int nCon = GetAbilityScore(oPC, ABILITY_CONSTITUTION, TRUE);//GetLocalInt(oPC, "BASE_CON");
int nclassDie;
int nFeatBonus = 0;
int nTotal;
string sIllegal;
if(GetHasFeat(FEAT_TOUGHNESS, oPC)) {
nFeatBonus = 1;
}
switch(nclass) {
case class_TYPE_BARBARIAN:
nclassDie = 12; break;
case class_TYPE_PALADIN:
case class_TYPE_RANGER:
case class_TYPE_FIGHTER:
nclassDie = 10; break;
case class_TYPE_DRUID:
case class_TYPE_MONK:
case class_TYPE_CLERIC:
nclassDie = 8; break;
case class_TYPE_ROGUE:
case class_TYPE_BARD:
nclassDie = 6; break;
case class_TYPE_SORCERER:
case class_TYPE_WIZARD:
nclassDie = 4; break;
default:
SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal class
sIllegal = "Illegal class Detected - Name: " + GetName(oPC) + "; Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
WriteTimestampedLogEntry(sIllegal);
SendMessageToAllDMs(sIllegal);
break;
}
int nRace = 0,nRaceType = GetRacialType(oPC);
if (nRaceType == RACIAL_TYPE_DWARF ||
nRaceType == RACIAL_TYPE_DWARF ||
nRaceType == RACIAL_TYPE_DWARF)
nRace = 2;
nTotal = nclassDie+nFeatBonus+GetBaseAbilityModifier(nCon)+nRace;
return nTotal;
}
int GetPointCostOfStat(int nScore) {
int nCost;
switch(nScore) {
case 8: nCost = 0; break;
case 9: nCost = 1; break;
case 10: nCost = 2; break;
case 11: nCost = 3; break;
case 12: nCost = 4; break;
case 13: nCost = 5; break;
case 14: nCost = 6; break;
case 15: nCost = 8; break;
case 16: nCost = 10; break;
case 17: nCost = 13; break;
case 18: nCost = 16; break;
default: nCost = 40; break;//any stat other than these indicates illegal edits, so we flag them illegal to start (total over 30 is illegal)
}
return nCost;
}
void main() {
object oPC = GetPCSpeaker();
if (GetIsObjectValid(GetItemPossessedBy(oPC, "PCList"))) return;//GetXP(oPC) != 0)
string sIllegal;
string sName = GetName(oPC);
string sPlayername = GetPCPlayerName(oPC);
int nStr = GetLocalInt(oPC, "BASE_STR");
int nDex = GetLocalInt(oPC, "BASE_DEX");
int nCon = GetLocalInt(oPC, "BASE_CON");
int nInt = GetLocalInt(oPC, "BASE_INT");
int nWis = GetLocalInt(oPC, "BASE_WIS");
int nCha = GetLocalInt(oPC, "BASE_CHA");
int nRace = GetRacialType(oPC);
int nPointTotal;
switch (nRace) {//neutralize racial bonuses
case RACIAL_TYPE_DWARF://2con -2cha
nCon = nCon - 2;
nCha = nCha +2;
break;
case RACIAL_TYPE_ELF://2dex -2con
nDex = nDex - 2;
nCon = nCon +2;
break;
case RACIAL_TYPE_GNOME://2con -2str
nCon = nCon - 2;
nStr = nStr +2;
break;
case RACIAL_TYPE_HALFLING://2dex -2str
nDex = nDex - 2;
nStr = nStr +2;
break;
case RACIAL_TYPE_HALFORC://2str -2int -2cha
nStr = nStr - 2;
nInt = nInt +2;
nCha = nCha +2;
break;
case RACIAL_TYPE_HUMAN:
case RACIAL_TYPE_HALFELF:
break;
default:
SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal race
sIllegal = "Illegal Race Detected - Name: " + GetName(oPC) + "; Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
WriteTimestampedLogEntry(sIllegal);
SendMessageToAllDMs(sIllegal);
break;
}
nPointTotal = GetPointCostOfStat(nStr) + GetPointCostOfStat(nDex) + GetPointCostOfStat(nCon) + GetPointCostOfStat(nInt) + GetPointCostOfStat(nWis) + GetPointCostOfStat(nCha);
if (nPointTotal > 30) {
SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal stats
sIllegal = "Illegal Stats Detected - Name: " + GetName(oPC) + "; Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
WriteTimestampedLogEntry(sIllegal);
SendMessageToAllDMs(sIllegal);
}
if (GetLegalHitPoints(oPC) < GetMaxHitPoints(oPC)) {
SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal stats
sIllegal = "Illegal Hit Points Detected - Name: " + GetName(oPC) + "; Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
WriteTimestampedLogEntry(sIllegal);
SendMessageToAllDMs(sIllegal);
}
if ((sName == "") || (GetBicFileName(oPC) == "")) {
SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal stats
sIllegal = "Illegal Name Detected - Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
SendMessageToPC(oPC, sIllegal);
WriteTimestampedLogEntry(sIllegal);
SendMessageToAllDMs(sIllegal);
}
if (GetLocalInt(oPC, "Accomplishments") != 0) {
SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal accomplishments
sIllegal = "Illegal Accomplishments Detected - Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
SendMessageToPC(oPC, sIllegal);
WriteTimestampedLogEntry(sIllegal);
SendMessageToAllDMs(sIllegal);
}
/* check for not-yet-active HG specific feats */
int i, nFeats = GetTotalKnownFeats(oPC);
for (i = 0; i < nFeats; i++) {
if (GetKnownFeat(oPC, i) >= 1995) {
SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal feats
sIllegal = "Illegal Feat " + IntToString(GetKnownFeat(oPC, i)) +
" Detected - Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
SendMessageToPC(oPC, sIllegal);
WriteTimestampedLogEntry(sIllegal);
SendMessageToAllDMs(sIllegal);
}
}
}
You'll note that that chunk has checks unique to my PW, checking to make sure that they havent made a same-name character to benefit from tags.
In any case, after you fire the last stat checking call off, the PC will have a local int "Hacker" set to 2 if they cheated, and you can do what you will with them in any node thereafter. I wait till the end, clean up the extra locals, and send them to a Cheater's Cell area if the got tagged. Here's the script I use, everything until the else statement in the main function is relevant to you:
[code=auto:0]
#include "hg_inc"
#include "hgll_func_inc"
#include "nw_i0_tool"
string GetWeaponResRef (int nBaseItem) {
switch (nBaseItem) {
case BASE_ITEM_BASTARDSWORD: return "nw_wswbs001";
case BASE_ITEM_BATTLEAXE: return "nw_waxbt001";
case BASE_ITEM_CLUB: return "nw_wblcl001";
case BASE_ITEM_DAGGER: return "nw_wswdg001";
case BASE_ITEM_DIREMACE: return "nw_wdbma001";
case BASE_ITEM_DOUBLEAXE: return "nw_wdbax001";
case BASE_ITEM_DWARVENWARAXE: return "x2_wdwraxe001";
case BASE_ITEM_GREATAXE: return "nw_waxgr001";
case BASE_ITEM_GREATSWORD: return "nw_wswgs001";
case BASE_ITEM_HALBERD: return "nw_wplhb001";
case BASE_ITEM_HANDAXE: return "nw_waxhn001";
case BASE_ITEM_HEAVYFLAIL: return "nw_wblfh001";
case BASE_ITEM_KAMA: return "nw_wspka001";
case BASE_ITEM_KATANA: return "nw_wswka001";
case BASE_ITEM_KUKRI: return "nw_wspku001";
case BASE_ITEM_LIGHTFLAIL: return "nw_wblfl001";
case BASE_ITEM_LIGHTHAMMER: return "nw_wblhl001";
case BASE_ITEM_LIGHTMACE: return "nw_wblml001";
case BASE_ITEM_LONGSWORD: return "nw_wswls001";
case BASE_ITEM_MORNINGSTAR: return "nw_wblms001";
case BASE_ITEM_QUARTERSTAFF: return "nw_wdbqs001";
case BASE_ITEM_RAPIER: return "nw_wswrp001";
case BASE_ITEM_SCIMITAR: return "nw_wswsc001";
case BASE_ITEM_SCYTHE: return "nw_wplsc001";
case BASE_ITEM_SHORTSPEAR: return "nw_wplss001";
case BASE_ITEM_SHORTSWORD: return "nw_wswss001";
case BASE_ITEM_SICKLE: return "nw_wspsc001";
case BASE_ITEM_TRIDENT: return "nw_wpltr001";
case BASE_ITEM_TWOBLADEDSWORD: return "nw_wdbsw001";
case BASE_ITEM_WARHAMMER: return "nw_wblhw001";
case BASE_ITEM_WHIP: return "x2_it_wpwhip";
}
return "";
}
string GetFocusedWeapon (object oPC, int nBaseItem) {
int i, nFeat;
string sRes;
for (i = 0; i <= BASE_ITEM_WHIP; i++) {
nFeat = GetWeaponFocusFeat(i);
if (nFeat > 0 && GetHasFeat(nFeat, oPC)) {
sRes = GetWeaponResRef(i);
if (sRes != "")
return sRes;
}
}
return GetWeaponResRef(nBaseItem);
}
void main() {
object oPC = GetPCSpeaker();
DeleteBaseAbilityMarkers(oPC);
DeleteLocalInt(oPC, "FeatCheckCount");
location voy;
int nHack = GetLocalInt(oPC, "Hacker");
if (nHack == 2) {
DeleteLocalInt(oPC, "Hacker");
voy = GetLocation(GetWaypointByTag("hacker_way"));
AssignCommand(oPC, ActionJumpToLocation(voy));
} else {
if (TestStringAgainstPattern("**[TEST]**", GetName(oPC)))
voy = GetLocation(GetWaypointByTag("funkywaypoint210"));
else
voy = GetLocation(GetWaypointByTag("voyage"));
if (!HasItem(oPC, "PCList")) {
int nGold = GetGold(oPC);
if (nGold > 0)
TakeGoldFromCreature(nGold, oPC, TRUE);
if (GetHitDice(oPC) == 1) {
object oItem;
string sAmmo = "nw_wthdt001", sArmor = "nw_cloth001", sShield = "nw_ashsw001", sWeapon = "nw_wswdg001";
switch (GetclassByPosition(1, oPC)) {
case class_TYPE_BARD:
sArmor = "nw_cloth021";
sShield = "nw_it_mglove005";
break;
case class_TYPE_BARBARIAN:
sAmmo = "nw_wthax001";
sArmor = "nw_aarcl010";
sShield = "nw_ashlw001";
sWeapon = GetFocusedWeapon(oPC, BASE_ITEM_BATTLEAXE);
break;
case class_TYPE_CLERIC:
sArmor = "nw_aarcl004";
sWeapon = "nw_wblml001";
break;
case class_TYPE_DRUID:
sArmor = "nw_aarcl008";
sWeapon = "nw_wspsc001";
break;
case class_TYPE_FIGHTER:
sAmmo = "nw_wthax001";
sArmor = "nw_aarcl006";
sShield = "nw_ashto001";
sWeapon = GetFocusedWeapon(oPC, BASE_ITEM_LONGSWORD);
break;
case class_TYPE_MONK:
sAmmo = "nw_wthsh001";
sArmor = "nw_cloth016";
sShield = "nw_it_mglove008";
sWeapon = "nw_wspka001";
break;
case class_TYPE_PALADIN:
sAmmo = "nw_wthax001";
sArmor = "nw_aarcl011";
sShield = "nw_ashto001";
sWeapon = GetFocusedWeapon(oPC, BASE_ITEM_WARHAMMER);
break;
case class_TYPE_RANGER:
sAmmo = "nw_wamar001";
sArmor = "nw_aarcl001";
sShield = "nw_wbwsh001";
sWeapon = GetFocusedWeapon(oPC, BASE_ITEM_SCIMITAR);
break;
case class_TYPE_ROGUE:
sAmmo = "nw_wamar001";
sArmor = "nw_aarcl001";
sShield = "nw_wbwsh001";
sWeapon = "nw_wswss001";
break;
case class_TYPE_SORCERER:
sAmmo = "nw_wambo001";
sArmor = "nw_cloth008";
sShield = "nw_wbwxl001";
break;
case class_TYPE_WIZARD:
sAmmo = "nw_wambo001";
sArmor = "nw_cloth005";
sShield = "nw_wbwxl001";
if (!GetKnowsSpell(SPELL_BURNING_HANDS, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_BURNING_HANDS);
if (!GetKnowsSpell(SPELL_CHARM_PERSON, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_CHARM_PERSON);
if (!GetKnowsSpell(SPELL_COLOR_SPRAY, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_COLOR_SPRAY);
if (!GetKnowsSpell(SPELL_ENDURE_ELEMENTS, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_ENDURE_ELEMENTS);
if (!GetKnowsSpell(SPELL_EXPEDITIOUS_RETREAT, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_EXPEDITIOUS_RETREAT);
if (!GetKnowsSpell(SPELL_GREASE, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_GREASE);
if (!GetKnowsSpell(SPELL_HORIZIKAULS_BOOM, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_HORIZIKAULS_BOOM);
if (!GetKnowsSpell(SPELL_ICE_DAGGER, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_ICE_DAGGER);
if (!GetKnowsSpell(SPELL_IDENTIFY, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_IDENTIFY);
if (!GetKnowsSpell(SPELL_IRONGUTS, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_IRONGUTS);
if (!GetKnowsSpell(SPELL_MAGE_ARMOR, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_MAGE_ARMOR);
if (!GetKnowsSpell(SPELL_MAGIC_MISSILE, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_MAGIC_MISSILE);
if (!GetKnowsSpell(SPELL_MAGIC_WEAPON, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_MAGIC_WEAPON);
if (!GetKnowsSpell(SPELL_NEGATIVE_ENERGY_RAY, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_NEGATIVE_ENERGY_RAY);
if (!GetKnowsSpell(SPELL_RAY_OF_ENFEEBLEMENT, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_RAY_OF_ENFEEBLEMENT);
if (!GetKnowsSpell(SPELL_SCARE, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_SCARE);
if (!GetKnowsSpell(SPELL_SHIELD, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_SHIELD);
if (!GetKnowsSpell(SPELL_SLEEP, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_SLEEP);
if (!GetKnowsSpell(SPELL_SUMMON_CREATURE_I, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_SUMMON_CREATURE_I);
if (!GetKnowsSpell(SPELL_TRUE_STRIKE, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_TRUE_STRIKE);
break;
default:
break;
}
SetIdentified((oItem = CreateItemOnObject(sAmmo, oPC)), TRUE);
SetItemStackSize(oItem, 99);
SetIdentified(CreateItemOnObject(sArmor, oPC), TRUE);
SetIdentified(CreateItemOnObject(sShield, oPC), TRUE);
SetIdentified(CreateItemOnObject(sWeapon, oPC), TRUE);
SetIdentified(CreateItemOnObject("nw_it_mpotion001", oPC, 50), TRUE);
SetIdentified(CreateItemOnObject("nw_it_torch001", oPC), TRUE);
SetIdentified(CreateItemOnObject("nw_it_contain001", oPC), TRUE);
}
GiveGoldToCreature(oPC, 10000);
CreateItemOnObject("pclist", oPC);
&