generated from Jaysyn/ModuleTemplate
1057 lines
37 KiB
Plaintext
1057 lines
37 KiB
Plaintext
|
|
//:: prc_craft_cv_inc.nss
|
|
|
|
#include "prc_craft_inc"
|
|
#include "inc_dynconv"
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Constant defintions */
|
|
//////////////////////////////////////////////////
|
|
|
|
//const int STAGE_ = ;
|
|
|
|
const int STAGE_START = 0;
|
|
const int STAGE_SELECT_SUBTYPE = 1;
|
|
const int STAGE_SELECT_COSTTABLEVALUE = 2;
|
|
const int STAGE_SELECT_PARAM1VALUE = 3;
|
|
const int STAGE_CONFIRM = 4;
|
|
const int STAGE_BANE = 5;
|
|
|
|
const int STAGE_CONFIRM_MAGIC = 7;
|
|
const int STAGE_APPEARANCE = 8;
|
|
const int STAGE_CLONE = 9;
|
|
const int STAGE_APPEARANCE_LIST = 10;
|
|
const int STAGE_APPEARANCE_VALUE = 11;
|
|
const int STAGE_CRAFT_GOLEM = 12;
|
|
const int STAGE_CRAFT_GOLEM_HD = 13;
|
|
const int STAGE_CRAFT_ALCHEMY = 14;
|
|
const int STAGE_CONFIRM_ALCHEMY = 15;
|
|
const int STAGE_CRAFT_POISON = 16;
|
|
const int STAGE_CONFIRM_POISON = 17;
|
|
const int STAGE_CRAFT_LICH = 18;
|
|
const int STAGE_CRAFT = 101;
|
|
const int STAGE_CRAFT_SELECT = 102;
|
|
const int STAGE_CRAFT_MASTERWORK = 103;
|
|
const int STAGE_CRAFT_AC = 104;
|
|
const int STAGE_CRAFT_MIGHTY = 105;
|
|
const int STAGE_CRAFT_CONFIRM = 106;
|
|
|
|
//const int STAGE_CRAFT = 101;
|
|
|
|
|
|
//const int CHOICE_ = ;
|
|
|
|
//these must be past the highest 2da entry to be read
|
|
const int CHOICE_FORGE = 20001;
|
|
const int CHOICE_BOOST = 20002;
|
|
const int CHOICE_BACK = 20003;
|
|
const int CHOICE_CLEAR = 20004;
|
|
const int CHOICE_CONFIRM = 20005;
|
|
const int CHOICE_SETNAME = 20006;
|
|
const int CHOICE_SETAPPEARANCE = 20007;
|
|
const int CHOICE_CLONE = 20008;
|
|
|
|
const int CHOICE_APPEARANCE_SHOUT = 20009;
|
|
const int CHOICE_APPEARANCE_SELECT = 20010;
|
|
|
|
const int CHOICE_PLUS_1 = 20011;
|
|
const int CHOICE_PLUS_10 = 20012;
|
|
const int CHOICE_MINUS_1 = 20013;
|
|
const int CHOICE_MINUS_10 = 20014;
|
|
|
|
const int CHOICE_CRAFT = 20101;
|
|
|
|
//const int NUM_MAX_COSTTABLEVALUES = 70;
|
|
//const int NUM_MAX_PARAM1VALUES = 70;
|
|
|
|
const int HAS_SUBTYPE = 1;
|
|
const int HAS_COSTTABLE = 2;
|
|
const int HAS_PARAM1 = 4;
|
|
|
|
const int STRREF_YES = 4752; // "Yes"
|
|
const int STRREF_NO = 4753; // "No"
|
|
|
|
const string PRC_CRAFT_ITEM = "PRC_CRAFT_ITEM";
|
|
const string PRC_CRAFT_TYPE = "PRC_CRAFT_TYPE";
|
|
const string PRC_CRAFT_SUBTYPE = "PRC_CRAFT_SUBTYPE";
|
|
const string PRC_CRAFT_SUBTYPEVALUE = "PRC_CRAFT_SUBTYPEVALUE";
|
|
const string PRC_CRAFT_COSTTABLE = "PRC_CRAFT_COSTTABLE";
|
|
const string PRC_CRAFT_COSTTABLEVALUE = "PRC_CRAFT_COSTTABLEVALUE";
|
|
const string PRC_CRAFT_PARAM1 = "PRC_CRAFT_PARAM1";
|
|
const string PRC_CRAFT_PARAM1VALUE = "PRC_CRAFT_PARAM1VALUE";
|
|
const string PRC_CRAFT_PROPLIST = "PRC_CRAFT_PROPLIST";
|
|
const string PRC_CRAFT_COST = "PRC_CRAFT_COST";
|
|
const string PRC_CRAFT_XP = "PRC_CRAFT_XP";
|
|
const string PRC_CRAFT_TIME = "PRC_CRAFT_TIME";
|
|
//const string PRC_CRAFT_BLUEPRINT = "PRC_CRAFT_BLUEPRINT";
|
|
const string PRC_CRAFT_CONVO_ = "PRC_CRAFT_CONVO_";
|
|
const string PRC_CRAFT_BASEITEMTYPE = "PRC_CRAFT_BASEITEMTYPE";
|
|
const string PRC_CRAFT_AC = "PRC_CRAFT_AC";
|
|
const string PRC_CRAFT_MIGHTY = "PRC_CRAFT_MIGHTY";
|
|
const string PRC_CRAFT_MATERIAL = "PRC_CRAFT_MATERIAL";
|
|
const string PRC_CRAFT_TAG = "PRC_CRAFT_TAG";
|
|
const string PRC_CRAFT_LINE = "PRC_CRAFT_LINE";
|
|
const string PRC_CRAFT_FILE = "PRC_CRAFT_FILE";
|
|
|
|
const string PRC_CRAFT_MAGIC_ENHANCE = "PRC_CRAFT_MAGIC_ENHANCE";
|
|
const string PRC_CRAFT_MAGIC_ADDITIONAL = "PRC_CRAFT_MAGIC_ADDITIONAL";
|
|
const string PRC_CRAFT_MAGIC_EPIC = "PRC_CRAFT_MAGIC_EPIC";
|
|
|
|
const string PRC_CRAFT_SCRIPT_STATE = "PRC_CRAFT_SCRIPT_STATE";
|
|
|
|
const string ARTIFICER_PREREQ_RACE = "ARTIFICER_PREREQ_RACE";
|
|
const string ARTIFICER_PREREQ_ALIGN = "ARTIFICER_PREREQ_ALIGN";
|
|
const string ARTIFICER_PREREQ_CLASS = "ARTIFICER_PREREQ_CLASS";
|
|
const string ARTIFICER_PREREQ_SPELL1 = "ARTIFICER_PREREQ_SPELL1";
|
|
const string ARTIFICER_PREREQ_SPELL2 = "ARTIFICER_PREREQ_SPELL2";
|
|
const string ARTIFICER_PREREQ_SPELL3 = "ARTIFICER_PREREQ_SPELL3";
|
|
const string ARTIFICER_PREREQ_SPELLOR1 = "ARTIFICER_PREREQ_SPELLOR1";
|
|
const string ARTIFICER_PREREQ_SPELLOR2 = "ARTIFICER_PREREQ_SPELLOR2";
|
|
const string ARTIFICER_PREREQ_COMPLETE = "ARTIFICER_PREREQ_COMPLETE";
|
|
|
|
const int PRC_CRAFT_STATE_NORMAL = 1;
|
|
const int PRC_CRAFT_STATE_MAGIC = 2;
|
|
|
|
const string PRC_CRAFT_HB = "PRC_CRAFT_HB";
|
|
|
|
const int SORT = TRUE; // If the sorting takes too much CPU, set to FALSE
|
|
const int DEBUG_LIST = FALSE;
|
|
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Function defintions */
|
|
//////////////////////////////////////////////////
|
|
|
|
void PrintList(object oPC)
|
|
{
|
|
string tp = "Printing list:\n";
|
|
string s = GetLocalString(oPC, "ForgeConvo_List_Head");
|
|
if(s == ""){
|
|
tp += "Empty\n";
|
|
}
|
|
else{
|
|
tp += s + "\n";
|
|
s = GetLocalString(oPC, "ForgeConvo_List_Next_" + s);
|
|
while(s != ""){
|
|
tp += "=> " + s + "\n";
|
|
s = GetLocalString(oPC, "ForgeConvo_List_Next_" + s);
|
|
}
|
|
}
|
|
|
|
DoDebug(tp);
|
|
}
|
|
|
|
/**
|
|
* Creates a linked list of entries that is sorted into alphabetical order
|
|
* as it is built.
|
|
* Assumption: Power names are unique.
|
|
*
|
|
* @param oPC The storage object aka whomever is gaining powers in this conversation
|
|
* @param sChoice The choice string
|
|
* @param nChoice The choice value
|
|
*/
|
|
|
|
void AddToTempList(object oPC, string sChoice, int nChoice)
|
|
{
|
|
if(DEBUG_LIST) DoDebug("\nAdding to temp list: '" + sChoice + "' - " + IntToString(nChoice));
|
|
if(DEBUG_LIST) PrintList(oPC);
|
|
// If there is nothing yet
|
|
if(!GetLocalInt(oPC, "PRC_CRAFT_CONVO_ListInited"))
|
|
{
|
|
SetLocalString(oPC, "PRC_CRAFT_CONVO_List_Head", sChoice);
|
|
SetLocalInt(oPC, "PRC_CRAFT_CONVO_List_" + sChoice, nChoice);
|
|
|
|
SetLocalInt(oPC, "PRC_CRAFT_CONVO_ListInited", TRUE);
|
|
}
|
|
else
|
|
{
|
|
// Find the location to instert into
|
|
string sPrev = "", sNext = GetLocalString(oPC, "PRC_CRAFT_CONVO_List_Head");
|
|
while(sNext != "" && StringCompare(sChoice, sNext) >= 0)
|
|
{
|
|
if(DEBUG_LIST) DoDebug("Comparison between '" + sChoice + "' and '" + sNext + "' = " + IntToString(StringCompare(sChoice, sNext)));
|
|
sPrev = sNext;
|
|
sNext = GetLocalString(oPC, "PRC_CRAFT_CONVO_List_Next_" + sNext);
|
|
}
|
|
|
|
// Insert the new entry
|
|
// Does it replace the head?
|
|
if(sPrev == "")
|
|
{
|
|
if(DEBUG_LIST) DoDebug("New head");
|
|
SetLocalString(oPC, "PRC_CRAFT_CONVO_List_Head", sChoice);
|
|
}
|
|
else
|
|
{
|
|
if(DEBUG_LIST) DoDebug("Inserting into position between '" + sPrev + "' and '" + sNext + "'");
|
|
SetLocalString(oPC, "PRC_CRAFT_CONVO_List_Next_" + sPrev, sChoice);
|
|
}
|
|
|
|
SetLocalString(oPC, "PRC_CRAFT_CONVO_List_Next_" + sChoice, sNext);
|
|
SetLocalInt(oPC, "PRC_CRAFT_CONVO_List_" + sChoice, nChoice);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads the linked list built with AddToTempList() to AddChoice() and
|
|
* deletes it.
|
|
*
|
|
* @param oPC A PC gaining powers at the moment
|
|
*/
|
|
|
|
void TransferTempList(object oPC)
|
|
{
|
|
string sChoice = GetLocalString(oPC, "PRC_CRAFT_CONVO_List_Head");
|
|
int nChoice = GetLocalInt (oPC, "PRC_CRAFT_CONVO_List_" + sChoice);
|
|
|
|
DeleteLocalString(oPC, "PRC_CRAFT_CONVO_List_Head");
|
|
string sPrev;
|
|
|
|
if(DEBUG_LIST) DoDebug("Head is: '" + sChoice + "' - " + IntToString(nChoice));
|
|
|
|
while(sChoice != "")
|
|
{
|
|
// Add the choice
|
|
AddChoice(sChoice, nChoice, oPC);
|
|
|
|
// Get next
|
|
sChoice = GetLocalString(oPC, "PRC_CRAFT_CONVO_List_Next_" + (sPrev = sChoice));
|
|
nChoice = GetLocalInt (oPC, "PRC_CRAFT_CONVO_List_" + sChoice);
|
|
|
|
if(DEBUG_LIST) DoDebug("Next is: '" + sChoice + "' - " + IntToString(nChoice) + "; previous = '" + sPrev + "'");
|
|
|
|
// Delete the already handled data
|
|
DeleteLocalString(oPC, "PRC_CRAFT_CONVO_List_Next_" + sPrev);
|
|
DeleteLocalInt (oPC, "PRC_CRAFT_CONVO_List_" + sPrev);
|
|
}
|
|
|
|
DeleteLocalInt(oPC, "PRC_CRAFT_CONVO_ListInited");
|
|
}
|
|
|
|
//Returns the next conversation stage according
|
|
// to item property
|
|
int GetNextItemPropStage(int nStage, object oPC, int nPropList)
|
|
{
|
|
nStage++;
|
|
if(nStage == STAGE_SELECT_SUBTYPE && !(nPropList & HAS_SUBTYPE))
|
|
nStage++;
|
|
if(nStage == STAGE_SELECT_COSTTABLEVALUE && !(nPropList & HAS_COSTTABLE))
|
|
nStage++;
|
|
if(nStage == STAGE_SELECT_PARAM1VALUE && !(nPropList & HAS_PARAM1))
|
|
nStage++;
|
|
MarkStageNotSetUp(nStage, oPC);
|
|
return nStage;
|
|
}
|
|
|
|
//Returns the previous conversation stage according
|
|
// to item property
|
|
int GetPrevItemPropStage(int nStage, object oPC, int nPropList)
|
|
{
|
|
nStage--;
|
|
if(nStage == STAGE_SELECT_PARAM1VALUE && !(nPropList & HAS_PARAM1))
|
|
nStage--;
|
|
if(nStage == STAGE_SELECT_COSTTABLEVALUE && !(nPropList & HAS_COSTTABLE))
|
|
nStage--;
|
|
if(nStage == STAGE_SELECT_SUBTYPE && !(nPropList & HAS_SUBTYPE))
|
|
nStage--;
|
|
MarkStageNotSetUp(nStage, oPC);
|
|
return nStage;
|
|
}
|
|
|
|
//hardcoded to save time/prevent tmi
|
|
int SkipLineSpells(int i)
|
|
{
|
|
switch(i)
|
|
{
|
|
//i +2
|
|
case 3:
|
|
case 6:
|
|
case 16:
|
|
case 22:
|
|
case 26:
|
|
case 29:
|
|
case 38:
|
|
case 41:
|
|
case 44:
|
|
case 58:
|
|
case 61:
|
|
case 64:
|
|
case 70:
|
|
case 73:
|
|
case 79:
|
|
case 82:
|
|
case 96:
|
|
case 111:
|
|
case 116:
|
|
case 134:
|
|
case 145:
|
|
case 165:
|
|
case 185:
|
|
case 193:
|
|
case 202:
|
|
case 289:
|
|
case 292:
|
|
case 295:
|
|
case 312:
|
|
case 516:
|
|
case 1017:
|
|
case 1038:
|
|
case 1041:
|
|
case 1068:
|
|
case 1082:
|
|
case 1090:
|
|
case 1099:
|
|
case 1104:
|
|
case 1107:
|
|
case 1134:
|
|
case 1363:
|
|
case 1430:
|
|
case 1435: i = i + 2; break;
|
|
|
|
//i +1
|
|
case 10:
|
|
case 12:
|
|
case 19:
|
|
case 21:
|
|
case 24:
|
|
case 32:
|
|
case 34:
|
|
case 36:
|
|
case 47:
|
|
case 51:
|
|
case 53:
|
|
case 56:
|
|
case 67:
|
|
case 85:
|
|
case 91:
|
|
case 93:
|
|
case 102:
|
|
case 107:
|
|
case 109:
|
|
case 114:
|
|
case 124:
|
|
case 132:
|
|
case 138:
|
|
case 141:
|
|
case 156:
|
|
case 163:
|
|
case 181:
|
|
case 191:
|
|
case 196:
|
|
case 199:
|
|
case 214:
|
|
case 218:
|
|
case 220:
|
|
case 222:
|
|
case 224:
|
|
case 235:
|
|
case 237:
|
|
case 248:
|
|
case 252:
|
|
case 256:
|
|
case 258:
|
|
case 263:
|
|
case 276:
|
|
case 285:
|
|
case 306:
|
|
case 309:
|
|
case 315:
|
|
case 325:
|
|
case 397:
|
|
case 462:
|
|
case 475:
|
|
case 485:
|
|
case 514:
|
|
case 949:
|
|
case 953:
|
|
case 1001:
|
|
case 1003:
|
|
case 1005:
|
|
case 1007:
|
|
case 1009:
|
|
case 1011:
|
|
case 1013:
|
|
case 1020:
|
|
case 1031:
|
|
case 1034:
|
|
case 1043:
|
|
case 1045:
|
|
case 1048:
|
|
case 1050:
|
|
case 1052:
|
|
case 1055:
|
|
case 1057:
|
|
case 1059:
|
|
case 1061:
|
|
case 1063:
|
|
case 1076:
|
|
case 1078:
|
|
case 1086:
|
|
case 1088:
|
|
case 1095:
|
|
case 1097:
|
|
case 1102:
|
|
case 1111:
|
|
case 1113:
|
|
case 1119:
|
|
case 1121:
|
|
case 1124:
|
|
case 1126:
|
|
case 1128:
|
|
case 1145:
|
|
case 1147:
|
|
case 1196:
|
|
case 1205:
|
|
case 1215:
|
|
case 1260:
|
|
case 1350: i = i + 1; break;
|
|
case 173: i = 179; break;
|
|
case 317: i = 321; break;
|
|
case 328: i = 345; break;
|
|
case 359: i = 360; break;
|
|
case 400: i = 450; break;
|
|
case 487: i = 514; break;
|
|
case 520: i = 538; break;
|
|
case 540: i = 899; break;
|
|
case 902: i = 903; break;
|
|
case 914: i = 928; break;
|
|
case 967: i = 1000; break;
|
|
case 1366: i = 1369; break;
|
|
case 1389: i = 1416; break;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
|
|
//added by MSB - hardcoded to prevent TMI
|
|
int SkipLineFeats(int i)
|
|
{
|
|
switch (i)
|
|
{
|
|
case 40: i = 99; break;
|
|
case 141: i = 201; break;
|
|
case 213: i = 257; break;
|
|
case 259: i = 260; break;
|
|
case 262: i = 264; break;
|
|
case 266: i = 343; break;
|
|
case 381: i = 394; break;
|
|
case 395: i = 24813; break;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
//hardcoded to save time/prevent tmi
|
|
int SkipLineItemprops(int i)
|
|
{
|
|
switch(i)
|
|
{
|
|
case 94: i = 100; break;
|
|
case 102: i = 133; break;
|
|
case 135: i = 150; break;
|
|
case 151: i = 200; break;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
//Adds names to a list based on sTable (2da), delayed recursion
|
|
// to avoid TMI
|
|
void PopulateList(object oPC, int MaxValue, int bSort, string sTable, object oItem = OBJECT_INVALID, int i = 0)
|
|
{
|
|
if(GetLocalInt(oPC, "DynConv_Waiting") == FALSE)
|
|
return;
|
|
if(i <= MaxValue)
|
|
{
|
|
int bValid = TRUE;
|
|
string sTemp = "";
|
|
if(sTable == "iprp_spells")
|
|
{
|
|
i = SkipLineSpells(i);
|
|
MaxValue = 1150; //MSB changed this from 540
|
|
}
|
|
else if(sTable == "IPRP_FEATS")
|
|
{
|
|
MaxValue = 24819;
|
|
i = SkipLineFeats(i);
|
|
}
|
|
else if(sTable == "itempropdef")
|
|
{
|
|
i = SkipLineItemprops(i);
|
|
bValid = ValidProperty(oItem, i);
|
|
if(bValid)
|
|
bValid = !GetPRCSwitch("PRC_CRAFT_DISABLE_itempropdef_" + IntToString(i));
|
|
}
|
|
else if(GetStringLeft(sTable, 6) == "craft_")
|
|
bValid = array_get_int(oPC, PRC_CRAFT_ITEMPROP_ARRAY, i);
|
|
sTemp = Get2DACache(sTable, "Name", i);
|
|
if((sTemp != "") && bValid)//this is going to kill
|
|
{
|
|
if(sTable == "iprp_spells")
|
|
{
|
|
AddToTempList(oPC, ActionString(GetStringByStrRef(StringToInt(sTemp))), i);
|
|
}
|
|
else
|
|
{
|
|
if(bSort)
|
|
AddToTempList(oPC, ActionString(GetStringByStrRef(StringToInt(sTemp))), i);
|
|
else
|
|
AddChoice(ActionString(GetStringByStrRef(StringToInt(sTemp))), i, oPC);
|
|
}
|
|
}
|
|
if(!(i % 100) && i) //i != 0, i % 100 == 0
|
|
//following line is for debugging
|
|
//FloatingTextStringOnCreature(sTable, oPC, FALSE);
|
|
FloatingTextStringOnCreature("*Tick*", oPC, FALSE);
|
|
|
|
}
|
|
else
|
|
{
|
|
if(bSort) TransferTempList(oPC);
|
|
DeleteLocalInt(oPC, "DynConv_Waiting");
|
|
FloatingTextStringOnCreature("*Done*", oPC, FALSE);
|
|
return;
|
|
}
|
|
DelayCommand(0.01, PopulateList(oPC, MaxValue, bSort, sTable, oItem, i + 1));
|
|
}
|
|
|
|
//use heartbeat
|
|
void ApplyProperties(object oPC, object oItem, itemproperty ip, int nCost, int nXP, string sFile, int nLine)
|
|
{
|
|
if(DEBUG) DoDebug("ApplyProperties: Starting with nCost=" + IntToString(nCost) +
|
|
", and Crafter GP =" + IntToString(GetGold(oPC)));
|
|
|
|
if(GetGold(oPC) < nCost)
|
|
{
|
|
FloatingTextStringOnCreature("Crafting: Insufficient gold!", oPC);
|
|
return;
|
|
}
|
|
int nHD = GetHitDice(oPC);
|
|
int nMinXP = nHD * (nHD - 1) * 500;
|
|
int nCurrentXP = GetXP(oPC);
|
|
if((nCurrentXP - nMinXP) < nXP)
|
|
{
|
|
FloatingTextStringOnCreature("Crafting: Insufficient XP!", oPC);
|
|
return;
|
|
}
|
|
if(GetItemPossessor(oItem) != oPC)
|
|
{
|
|
FloatingTextStringOnCreature("Crafting: You do not have the item!", oPC);
|
|
return;
|
|
}
|
|
|
|
if(DEBUG) DoDebug("ApplyProperties: Passed validation, about to apply properties");
|
|
|
|
if(nLine == -1)
|
|
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
|
|
else if(nLine == -2)
|
|
{ //clone item
|
|
CopyItem(oItem, oPC, TRUE);
|
|
}
|
|
else
|
|
{
|
|
string sPropertyType = Get2DACache(sFile, "PropertyType", nLine);
|
|
if(sPropertyType == "M")
|
|
{ //checking required spells
|
|
if(!CheckCraftingSpells(oPC, sFile, nLine, TRUE))
|
|
{
|
|
FloatingTextStringOnCreature("Crafting: Required spells not available!", oPC);
|
|
return;
|
|
}
|
|
}
|
|
else if(sPropertyType == "P")
|
|
{
|
|
if(!CheckCraftingPowerPoints(oPC, sFile, nLine, TRUE))
|
|
{
|
|
FloatingTextStringOnCreature("Crafting: Insufficient power points!", oPC);
|
|
return;
|
|
}
|
|
}
|
|
if(DEBUG) DoDebug("ApplyProperties: Calling ApplyItemProps()");
|
|
ApplyItemProps(oItem, sFile, nLine);
|
|
}
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_BREACH), oPC);
|
|
|
|
// With this conditional logic:
|
|
if(GetLocalInt(oPC, "PRC_CRAFT_RESTORED"))
|
|
{
|
|
AssignCommand(oPC, ClearAllActions());
|
|
if(DEBUG) DoDebug("ApplyProperties: About to call TakeGoldFromCreature() with cost=" + IntToString(nCost));
|
|
AssignCommand(oPC, TakeGoldFromCreature(nCost, oPC, TRUE));
|
|
SpendXP(oPC, nXP);
|
|
|
|
DeleteLocalInt(oPC, "PRC_CRAFT_RESTORED");
|
|
}
|
|
else
|
|
{
|
|
AssignCommand(oPC, ClearAllActions());
|
|
if(DEBUG) DoDebug("ApplyProperties: About to call TakeGoldFromCreature() with cost=" + IntToString(nCost));
|
|
AssignCommand(oPC, TakeGoldFromCreature(nCost, oPC, TRUE));
|
|
if(DEBUG) DoDebug("ApplyProperties: TakeGoldFromCreature() completed, new gold =" + IntToString(GetGold(oPC)));
|
|
SpendXP(oPC, nXP);
|
|
if(DEBUG) DoDebug("ApplyProperties: XP deduction completed, new XP=" + IntToString(GetXP(oPC)));
|
|
}
|
|
|
|
//if(DEBUG) DoDebug("ApplyProperties: About to deduct gold ("+IntToString(nCost)+") and XP ("+IntToString(nCost)+").");
|
|
//TakeGoldFromCreature(nCost, oPC, TRUE);
|
|
//SetXP(oPC, GetXP(oPC) - nXP);
|
|
|
|
if(DEBUG) DoDebug("ApplyProperties: Completed successfully");
|
|
}
|
|
|
|
//use heartbeat
|
|
void CreateGolem(object oPC, int nCost, int nXP, string sFile, int nLine)
|
|
{
|
|
if(GetGold(oPC) < nCost)
|
|
{
|
|
FloatingTextStringOnCreature("Crafting: Insufficient gold!", oPC);
|
|
return;
|
|
}
|
|
int nHD = GetHitDice(oPC);
|
|
int nMinXP = nHD * (nHD - 1) * 500;
|
|
int nCurrentXP = GetXP(oPC);
|
|
if((nCurrentXP - nMinXP) < nXP)
|
|
{
|
|
FloatingTextStringOnCreature("Crafting: Insufficient XP!", oPC);
|
|
return;
|
|
}
|
|
string sPropertyType = Get2DACache(sFile, "CasterType", nLine);
|
|
if(sPropertyType == "M")
|
|
{ //checking required spells
|
|
if(!CheckCraftingSpells(oPC, sFile, nLine, TRUE))
|
|
{
|
|
FloatingTextStringOnCreature("Crafting: Required spells not available!", oPC);
|
|
return;
|
|
}
|
|
}
|
|
else if(sPropertyType == "P")
|
|
{
|
|
if(!CheckCraftingPowerPoints(oPC, sFile, nLine, TRUE))
|
|
{
|
|
FloatingTextStringOnCreature("Crafting: Insufficient power points!", oPC);
|
|
return;
|
|
}
|
|
}
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_BREACH), oPC);
|
|
TakeGoldFromCreature(nCost, oPC, TRUE);
|
|
SetXP(oPC, GetXP(oPC) - nXP);
|
|
}
|
|
|
|
int ArtificerPrereqCheck(object oPC, string sFile, int nLine, int nCost)
|
|
{
|
|
string sTemp, sSub, sSpell;
|
|
int nRace, nAlignGE, nAlignLC, nClass, i, j, bBreak, nLength, nPosition, nTemp;
|
|
int nSpell1, nSpell2, nSpell3, nSpellOR1, nSpellOR2;
|
|
int nDays = nCost / 1000; //one set of UMD checks per "day" spent crafting
|
|
if(nCost % 1000) nDays++;
|
|
sTemp = Get2DACache(sFile, "PrereqMisc", nLine);
|
|
sSpell = Get2DACache(sFile, "Spells", nLine);
|
|
if(sTemp == "")
|
|
{
|
|
bBreak = TRUE;
|
|
nRace = -1;
|
|
nAlignGE = -1;
|
|
nAlignLC = -1;
|
|
nClass = -1;
|
|
}
|
|
nLength = GetStringLength(sTemp);
|
|
for(i = 0; i < 5; i++)
|
|
{
|
|
if(bBreak)
|
|
break;
|
|
nPosition = FindSubString(sTemp, "_");
|
|
sSub = (nPosition == -1) ? sTemp : GetStringLeft(sTemp, nPosition);
|
|
nLength -= (nPosition + 1);
|
|
if(sSub == "*")
|
|
nTemp = -1;
|
|
else
|
|
nTemp = StringToInt(sSub);
|
|
switch(i)
|
|
{
|
|
case 0:
|
|
{
|
|
nRace = (MyPRCGetRacialType(oPC) == nTemp) ? -1 : nTemp;
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
//can't emulate feat requirement
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
nAlignGE = -1;
|
|
if(sSub == "G") nAlignGE = (GetAlignmentGoodEvil(oPC) == ALIGNMENT_GOOD) ? -1 : ALIGNMENT_GOOD;
|
|
else if(sSub == "E") nAlignGE = (GetAlignmentGoodEvil(oPC) == ALIGNMENT_EVIL) ? -1 : ALIGNMENT_EVIL;
|
|
else if(sSub == "N") nAlignGE = (GetAlignmentGoodEvil(oPC) == ALIGNMENT_NEUTRAL) ? -1 : ALIGNMENT_NEUTRAL;
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
nAlignLC = -1;
|
|
if(sSub == "L") nAlignLC = (GetAlignmentLawChaos(oPC) == ALIGNMENT_LAWFUL) ? -1 : ALIGNMENT_LAWFUL;
|
|
if(sSub == "C") nAlignLC = (GetAlignmentLawChaos(oPC) == ALIGNMENT_CHAOTIC) ? -1 : ALIGNMENT_CHAOTIC;
|
|
if(sSub == "N") nAlignLC = (GetAlignmentLawChaos(oPC) == ALIGNMENT_NEUTRAL) ? -1 : ALIGNMENT_NEUTRAL;
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
nClass = (GetLevelByClass(nTemp, oPC)) ? -1 : nTemp;
|
|
break;
|
|
}
|
|
}
|
|
sTemp = GetSubString(sTemp, nPosition + 1, nLength);
|
|
}
|
|
if(sSpell == "")
|
|
{
|
|
nSpell1 = -1;
|
|
nSpell2 = -1;
|
|
nSpell3 = -1;
|
|
nSpellOR1 = -1;
|
|
nSpellOR2 = -1;
|
|
}
|
|
else
|
|
{
|
|
for(i = 0; i < 5; i++)
|
|
{
|
|
nPosition = FindSubString(sTemp, "_");
|
|
sSub = (nPosition == -1) ? sTemp : GetStringLeft(sTemp, nPosition);
|
|
nLength -= (nPosition + 1);
|
|
if(sSub == "*")
|
|
nTemp = -1;
|
|
else
|
|
{
|
|
nTemp = StringToInt(sSub);
|
|
switch(i)
|
|
{
|
|
case 0:
|
|
{ //storing the spell level and assuming it's a valid number
|
|
nSpell1 = (PRCGetHasSpell(nTemp, oPC)) ? -1 : StringToInt(Get2DACache("spells", "Innate", nTemp)) + 20;
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
nSpell2 = (PRCGetHasSpell(nTemp, oPC)) ? -1 : StringToInt(Get2DACache("spells", "Innate", nTemp)) + 20;
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
nSpell3 = (PRCGetHasSpell(nTemp, oPC)) ? -1 : StringToInt(Get2DACache("spells", "Innate", nTemp)) + 20;
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
nSpellOR1 = (PRCGetHasSpell(nTemp, oPC)) ? -1 : StringToInt(Get2DACache("spells", "Innate", nTemp)) + 20;
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
nSpellOR2 = (PRCGetHasSpell(nTemp, oPC)) ? -1 : StringToInt(Get2DACache("spells", "Innate", nTemp)) + 20;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
sTemp = GetSubString(sTemp, nPosition + 1, nLength);
|
|
}
|
|
}
|
|
int bTake10 = GetHasFeat(FEAT_SKILL_MASTERY_ARTIFICER, oPC) ? 10 : -1;
|
|
for(i = 0; i <= nDays; i++) //with extra last-ditch roll
|
|
{
|
|
if((nRace == -1) &&
|
|
(nAlignGE == -1) &&
|
|
(nAlignLC == -1) &&
|
|
(nClass == -1) &&
|
|
(nSpell1 == -1) &&
|
|
(nSpell2 == -1) &&
|
|
(nSpell3 == -1) &&
|
|
(nSpellOR1 == -1) &&
|
|
(nSpellOR2 == -1)
|
|
)
|
|
return TRUE;
|
|
|
|
if(nRace != -1) nRace = (GetPRCIsSkillSuccessful(oPC, SKILL_USE_MAGIC_DEVICE, 25, bTake10)) ? -1 : nRace;
|
|
if(nAlignGE != -1) nAlignGE = (GetPRCIsSkillSuccessful(oPC, SKILL_USE_MAGIC_DEVICE, 30, bTake10)) ? -1 : nAlignGE;
|
|
if(nAlignLC != -1) nAlignLC = (GetPRCIsSkillSuccessful(oPC, SKILL_USE_MAGIC_DEVICE, 30, bTake10)) ? -1 : nAlignLC;
|
|
if(nClass != -1) nClass = (GetPRCIsSkillSuccessful(oPC, SKILL_USE_MAGIC_DEVICE, 21, bTake10)) ? -1 : nClass;
|
|
if(nSpell1 != -1) nSpell1 = (GetPRCIsSkillSuccessful(oPC, SKILL_USE_MAGIC_DEVICE, nSpell1, bTake10)) ? -1 : nSpell1;
|
|
if(nSpell2 != -1) nSpell2 = (GetPRCIsSkillSuccessful(oPC, SKILL_USE_MAGIC_DEVICE, nSpell2, bTake10)) ? -1 : nSpell2;
|
|
if(nSpell3 != -1) nSpell3 = (GetPRCIsSkillSuccessful(oPC, SKILL_USE_MAGIC_DEVICE, nSpell3, bTake10)) ? -1 : nSpell3;
|
|
if(nSpellOR1 != -1) nSpellOR1 = (GetPRCIsSkillSuccessful(oPC, SKILL_USE_MAGIC_DEVICE, nSpellOR1, bTake10)) ? -1 : nSpellOR1;
|
|
if(nSpellOR2 != -1) nSpellOR2 = (GetPRCIsSkillSuccessful(oPC, SKILL_USE_MAGIC_DEVICE, nSpellOR2, bTake10)) ? -1 : nSpellOR2;
|
|
}
|
|
if((nRace == -1) &&
|
|
(nAlignGE == -1) &&
|
|
(nAlignLC == -1) &&
|
|
(nClass == -1) &&
|
|
(nSpell1 == -1) &&
|
|
(nSpell2 == -1) &&
|
|
(nSpell3 == -1) &&
|
|
(nSpellOR1 == -1) &&
|
|
(nSpellOR2 == -1)
|
|
)
|
|
return TRUE;
|
|
else
|
|
return FALSE; //made all the UMD rolls allocated and still failed
|
|
}
|
|
|
|
// Save crafting state during crafting
|
|
void SaveCraftingState(object oPC)
|
|
{
|
|
if(DEBUG) DoDebug("prc_craft_cv_inc >> SaveCraftingState called for " + GetName(oPC));
|
|
|
|
if(GetLocalInt(oPC, PRC_CRAFT_HB))
|
|
{
|
|
if(DEBUG) DoDebug("prc_craft_cv_inc >> SaveCraftingState: Player is crafting, saving state...");
|
|
|
|
// Get the crafting item
|
|
object oItem = GetLocalObject(oPC, PRC_CRAFT_ITEM);
|
|
|
|
// Save item identification info
|
|
SQLocalsPlayer_SetString(oPC, "crafting_item_name", GetName(oItem));
|
|
SQLocalsPlayer_SetString(oPC, "crafting_item_tag", GetTag(oItem));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_item_basetype", GetBaseItemType(oItem));
|
|
|
|
// Save UUID if not already saved
|
|
string sItemUUID = SQLocalsPlayer_GetString(oPC, "crafting_item_uuid");
|
|
if(sItemUUID == "")
|
|
{
|
|
sItemUUID = GetObjectUUID(oItem);
|
|
SQLocalsPlayer_SetString(oPC, "crafting_item_uuid", sItemUUID);
|
|
if(DEBUG) DoDebug("prc_craft_cv_inc >> SaveCraftingState: Generated and saved new UUID: " + sItemUUID);
|
|
}
|
|
|
|
// Get crafting cost values
|
|
int nCostDiff = GetLocalInt(oPC, PRC_CRAFT_COST);
|
|
int nXPDiff = GetLocalInt(oPC, PRC_CRAFT_XP);
|
|
int nRounds = GetLocalInt(oPC, PRC_CRAFT_TIME);
|
|
|
|
// Save all basic crafting parameters
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_cost", nCostDiff);
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_xp", nXPDiff);
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_rounds", nRounds);
|
|
SQLocalsPlayer_SetString(oPC, "crafting_file", GetLocalString(oPC, PRC_CRAFT_FILE));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_line", GetLocalInt(oPC, PRC_CRAFT_LINE));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_active", 1);
|
|
|
|
// Save item property components for reconstruction
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_ip_type", GetLocalInt(oPC, "PRC_CRAFT_IP_TYPE"));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_ip_subtype", GetLocalInt(oPC, "PRC_CRAFT_IP_SUBTYPE"));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_ip_costtable", GetLocalInt(oPC, "PRC_CRAFT_IP_COSTTABLE"));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_ip_param1", GetLocalInt(oPC, "PRC_CRAFT_IP_PARAM1"));
|
|
|
|
// Save item property parameters
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_type", GetLocalInt(oPC, PRC_CRAFT_TYPE));
|
|
SQLocalsPlayer_SetString(oPC, "crafting_subtype", GetLocalString(oPC, PRC_CRAFT_SUBTYPE));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_subtypevalue", GetLocalInt(oPC, PRC_CRAFT_SUBTYPEVALUE));
|
|
SQLocalsPlayer_SetString(oPC, "crafting_costtable", GetLocalString(oPC, PRC_CRAFT_COSTTABLE));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_costtablevalue", GetLocalInt(oPC, PRC_CRAFT_COSTTABLEVALUE));
|
|
SQLocalsPlayer_SetString(oPC, "crafting_param1", GetLocalString(oPC, PRC_CRAFT_PARAM1));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_param1value", GetLocalInt(oPC, PRC_CRAFT_PARAM1VALUE));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_proplist", GetLocalInt(oPC, PRC_CRAFT_PROPLIST));
|
|
|
|
// Save item properties
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_baseitemtype", GetLocalInt(oPC, PRC_CRAFT_BASEITEMTYPE));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_time", nRounds);
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_material", GetLocalInt(oPC, PRC_CRAFT_MATERIAL));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_mighty", GetLocalInt(oPC, PRC_CRAFT_MIGHTY));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_ac", GetLocalInt(oPC, PRC_CRAFT_AC));
|
|
SQLocalsPlayer_SetString(oPC, "crafting_tag", GetLocalString(oPC, PRC_CRAFT_TAG));
|
|
|
|
// Save magic crafting variables
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_enhancement", GetLocalInt(oPC, PRC_CRAFT_MAGIC_ENHANCE));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_additional", GetLocalInt(oPC, PRC_CRAFT_MAGIC_ADDITIONAL));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_epic", GetLocalInt(oPC, PRC_CRAFT_MAGIC_EPIC));
|
|
|
|
// Save system state variables
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_script_state", GetLocalInt(oPC, PRC_CRAFT_SCRIPT_STATE));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_token", GetLocalInt(oPC, PRC_CRAFT_TOKEN));
|
|
|
|
if(DEBUG) DoDebug("DEBUG: Crafting state saved - rounds: " + IntToString(nRounds));
|
|
}
|
|
}
|
|
|
|
|
|
/* // Save crafting state on logout, pause concentration checks & time tracking
|
|
void SaveCraftingState(object oPC)
|
|
{
|
|
if(GetLocalInt(oPC, "PRC_CRAFT_HB"))
|
|
{
|
|
// Get all crafting parameters
|
|
object oItem = GetLocalObject(oPC, "PRC_CRAFT_ITEM");
|
|
int nCost = GetLocalInt(oPC, "PRC_CRAFT_COST");
|
|
int nXP = GetLocalInt(oPC, "PRC_CRAFT_XP");
|
|
int nRounds = GetLocalInt(oPC, "PRC_CRAFT_ROUNDS");
|
|
string sFile = GetLocalString(oPC, "PRC_CRAFT_FILE");
|
|
int nLine = GetLocalInt(oPC, "PRC_CRAFT_LINE");
|
|
|
|
// Save all parameters to database
|
|
SQLocalsPlayer_SetObject(oPC, "crafting_item", oItem);
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_cost", nCost);
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_xp", nXP);
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_rounds", nRounds);
|
|
SQLocalsPlayer_SetString(oPC, "crafting_file", sFile);
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_line", nLine);
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_active", 1);
|
|
|
|
// Save logout time using PRC time system
|
|
struct time tLogoutTime = GetTimeAndDate();
|
|
SetPersistantLocalTime(oPC, "crafting_logout_time", tLogoutTime);
|
|
|
|
// Remove concentration monitoring and clear heartbeat
|
|
RemoveEventScript(oPC, EVENT_VIRTUAL_ONDAMAGED, "prc_od_conc");
|
|
DeleteLocalInt(oPC, "PRC_CRAFT_HB");
|
|
}
|
|
} */
|
|
|
|
object GetItemByUUID(object oPC, string sUUID)
|
|
{
|
|
if(DEBUG) DoDebug("prc_craft_cv_inc >> GetItemByUUID | Searching for item with UUID: " + sUUID);
|
|
|
|
// Check player's inventory
|
|
object oItem = GetFirstItemInInventory(oPC);
|
|
while(GetIsObjectValid(oItem))
|
|
{
|
|
if(GetObjectUUID(oItem) == sUUID)
|
|
{
|
|
if(DEBUG) DoDebug("prc_craft_cv_inc >> GetItemByUUID | Found item in player inventory: " + GetName(oItem));
|
|
return oItem;
|
|
}
|
|
oItem = GetNextItemInInventory(oPC);
|
|
}
|
|
|
|
// Check equipped slots
|
|
int i;
|
|
for(i = 0; i < NUM_INVENTORY_SLOTS; i++)
|
|
{
|
|
oItem = GetItemInSlot(i, oPC);
|
|
if(GetIsObjectValid(oItem) && GetObjectUUID(oItem) == sUUID)
|
|
{
|
|
if(DEBUG) DoDebug("prc_craft_cv_inc >> GetItemByUUID | Found equipped item: " + GetName(oItem));
|
|
return oItem;
|
|
}
|
|
}
|
|
|
|
// Check the craft storage chest
|
|
object oChest = GetCraftChest();
|
|
if(GetIsObjectValid(oChest))
|
|
{
|
|
oItem = GetFirstItemInInventory(oChest);
|
|
while(GetIsObjectValid(oItem))
|
|
{
|
|
if(GetObjectUUID(oItem) == sUUID)
|
|
{
|
|
if(DEBUG) DoDebug("prc_craft_cv_inc >> GetItemByUUID | Found item in craft chest: " + GetName(oItem));
|
|
return oItem;
|
|
}
|
|
oItem = GetNextItemInInventory(oChest);
|
|
}
|
|
}
|
|
|
|
// Check temporary craft chest
|
|
object oTempChest = GetTempCraftChest();
|
|
if(GetIsObjectValid(oTempChest))
|
|
{
|
|
oItem = GetFirstItemInInventory(oTempChest);
|
|
while(GetIsObjectValid(oItem))
|
|
{
|
|
if(GetObjectUUID(oItem) == sUUID)
|
|
{
|
|
if(DEBUG) DoDebug("prc_craft_cv_inc >> GetItemByUUID | Found item in temp craft chest: " + GetName(oItem));
|
|
return oItem;
|
|
}
|
|
oItem = GetNextItemInInventory(oTempChest);
|
|
}
|
|
}
|
|
|
|
if(DEBUG) DoDebug("prc_craft_cv_inc >> GetItemByUUID | Item not found with UUID: " + sUUID);
|
|
return OBJECT_INVALID;
|
|
}
|
|
|
|
|
|
void CraftingHB(object oPC, object oItem, itemproperty ip, int nCost, int nXP, string sFile, int nLine, int nRounds)
|
|
{
|
|
// Save current timestamp for offline progress calculation
|
|
int nCurrentTime = GetCurrentUnixTimestamp();
|
|
if(nCurrentTime > 0)
|
|
{
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_last_timestamp", nCurrentTime);
|
|
}
|
|
|
|
// Set the heartbeat flag
|
|
SetLocalInt(oPC, PRC_CRAFT_HB, 1);
|
|
|
|
// Set database flag for persistence tracking
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_active", 1);
|
|
|
|
// Update local variables for heartbeat logic
|
|
SetLocalInt(oPC, PRC_CRAFT_TIME, nRounds);
|
|
SetLocalInt(oPC, PRC_CRAFT_COST, nCost);
|
|
SetLocalInt(oPC, PRC_CRAFT_XP, nXP);
|
|
SetLocalString(oPC, PRC_CRAFT_FILE, sFile);
|
|
SetLocalInt(oPC, PRC_CRAFT_LINE, nLine);
|
|
|
|
// Store the item property components for reconstruction
|
|
if(GetIsItemPropertyValid(ip))
|
|
{
|
|
SetLocalInt(oPC, "PRC_CRAFT_IP_TYPE", GetItemPropertyType(ip));
|
|
SetLocalInt(oPC, "PRC_CRAFT_IP_SUBTYPE", GetItemPropertySubType(ip));
|
|
SetLocalInt(oPC, "PRC_CRAFT_IP_COSTTABLE", GetItemPropertyCostTableValue(ip));
|
|
SetLocalInt(oPC, "PRC_CRAFT_IP_PARAM1", GetItemPropertyParam1Value(ip));
|
|
}
|
|
|
|
// Save current crafting state continuously for persistence
|
|
if(GetPRCSwitch(PRC_CRAFTING_TIME_SCALE) > 1)
|
|
{
|
|
// Store the CURRENT rounds value in database
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_rounds", nRounds);
|
|
SaveCraftingState(oPC);
|
|
}
|
|
|
|
if(GetBreakConcentrationCheck(oPC))
|
|
{
|
|
FloatingTextStringOnCreature("Crafting: Concentration lost!", oPC);
|
|
DeleteLocalInt(oPC, PRC_CRAFT_HB);
|
|
RemoveEventScript(oPC, EVENT_VIRTUAL_ONDAMAGED, "prc_od_conc");
|
|
// Clear database state
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_active", 0);
|
|
return;
|
|
}
|
|
|
|
if(nRounds == 0 || GetPCPublicCDKey(oPC) == "") //default to zero time if single player
|
|
{
|
|
if(DEBUG) DoDebug("prc_craft_cv_inc >> CraftHB() | Crafting completion - nCost: " + IntToString(nCost) + ", nLine: " + IntToString(nLine));
|
|
|
|
RemoveEventScript(oPC, EVENT_VIRTUAL_ONDAMAGED, "prc_od_conc");
|
|
if(GetLevelByClass(CLASS_TYPE_ARTIFICER, oPC))
|
|
{
|
|
if(!ArtificerPrereqCheck(oPC, sFile, nLine, nCost))
|
|
{
|
|
FloatingTextStringOnCreature("Crafting Failed!", oPC);
|
|
DeleteLocalInt(oPC, PRC_CRAFT_HB);
|
|
TakeGoldFromCreature(nCost, oPC, TRUE);
|
|
SetXP(oPC, PRCMax(GetXP(oPC) - nXP, GetHitDice(oPC) * (GetHitDice(oPC) - 1) * 500));
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_active", 0);
|
|
return;
|
|
}
|
|
}
|
|
FloatingTextStringOnCreature("Crafting Complete!", oPC);
|
|
if(DEBUG) DoDebug("prc_craft_cv_inc >> CraftHB() | Entering ApplyProperties() - nCost: " + IntToString(nCost) + ", nLine: " + IntToString(nLine));
|
|
ApplyProperties(oPC, oItem, ip, nCost, nXP, sFile, nLine);
|
|
DeleteLocalInt(oPC, PRC_CRAFT_HB);
|
|
|
|
if(GetLocalInt(oPC, "PRC_CRAFT_REMOVE_MASTERWORK"))
|
|
{
|
|
RemoveMasterworkProperties(oItem);
|
|
DeleteLocalInt(oPC, "PRC_CRAFT_REMOVE_MASTERWORK");
|
|
}
|
|
|
|
// Clear database state on completion
|
|
SQLocalsPlayer_SetInt(oPC, "crafting_active", 0);
|
|
}
|
|
else
|
|
{
|
|
if(DEBUG) DoDebug("prc_craft_cv_inc >> CraftHB() | Continuing CraftingHB() - nCost: " + IntToString(nCost) + ", nLine: " + IntToString(nLine));
|
|
FloatingTextStringOnCreature("Crafting: " + IntToString(nRounds) + " round(s) remaining", oPC);
|
|
DelayCommand(6.0, CraftingHB(oPC, oItem, ip, nCost, nXP, sFile, nLine, nRounds - 1));
|
|
}
|
|
}
|
|
|
|
//;: void main(){} |