generated from Jaysyn/ModuleTemplate
1197 lines
49 KiB
Plaintext
1197 lines
49 KiB
Plaintext
#include "x3_inc_horse"
|
|
#include "prc_inc_racial"
|
|
|
|
// DMFI DM Start Area 0.01b
|
|
// by OldManWhistler
|
|
|
|
// *****************************************************************************
|
|
// ** CONFIGURATION (modify this section to suit your module)
|
|
// *****************************************************************************
|
|
|
|
// STARTING LEVEL/XP
|
|
// Specify the starting level. If this is set to zero, then it will give the
|
|
// specific amount of XP specified by DMSTART_GIVE_XP.
|
|
const int DMSTART_GIVE_LEVEL = 3;
|
|
// This is the amount of XP given if DMSTART_GIVE_LEVEL = 0;
|
|
const int DMSTART_GIVE_XP = 0;
|
|
|
|
// STARTING GOLD
|
|
// If this is set to -1 then it will give the amount of gold appropriate for
|
|
// level as per the DMG. Otherwise it will give the value specified. A value of
|
|
// will mean the player will get no starting gold.
|
|
const int DMSTART_GIVE_GP = 1300;
|
|
// If this is set to TRUE then it will give the average GP for level 1 characters
|
|
// by class instead of rolling for each character.
|
|
const int DMSTART_AVERAGE_GP_LEVEL_1 = TRUE;
|
|
|
|
// STARTING ITEMS
|
|
// Give DMs the items in the DM chest. The chest is in the DM Control Room.
|
|
const int DMSTART_GIVE_ITEMS_DM = TRUE;
|
|
// Give players the items in the player chests. The chest is in the DM Control Room.
|
|
const int DMSTART_GIVE_ITEMS_PC = TRUE;
|
|
// Give players the DMFI voice widgets appropriate for their race/class.
|
|
const int DMSTART_GIVE_ITEMS_LANGUAGE = TRUE;
|
|
|
|
// MERCHANT
|
|
// These settings will affect all merchants in the starting area.
|
|
// If set to TRUE, merchant prices will be modified by the Appraise skill.
|
|
const int DMSTART_MERCHANTS_USE_APPRAISE = TRUE;
|
|
// Mark up (-100 to 100) on items sold by merchants.
|
|
const int DMSTART_MERCHANTS_MARK_UP_SELL = 0;
|
|
// Mark down (-100 to 100) on items bought by merchants.
|
|
const int DMSTART_MERCHANTS_MARK_DOWN_BUY = 0;
|
|
|
|
// DOORS
|
|
// These settings control which doors will automatically be opened in the
|
|
// starting area. You can always control the doors in-game by right clicking on
|
|
// them and choosing DM Lock/DM Unlock, Open/Close.
|
|
// If TRUE then the newbie merchant area will start out unlocked and opened.
|
|
const int DMSTART_UNLOCK_MERCHANT = FALSE;
|
|
// If TRUE then the magic item merchant area will start out unlocked and opened.
|
|
// NOTE: it can only be accessed it DMSTART_UNLOCK_MERCHANT is true.
|
|
const int DMSTART_UNLOCK_MAGIC = FALSE;
|
|
// If TRUE then the west area will start out unlocked and opened.
|
|
const int DMSTART_UNLOCK_WEST = FALSE;
|
|
// If TRUE then the east area will start out unlocked and opened.
|
|
const int DMSTART_UNLOCK_EAST = FALSE;
|
|
// If TRUE then the north area will start out unlocked and opened.
|
|
const int DMSTART_UNLOCK_NORTH = FALSE;
|
|
|
|
// JOURNAL ENTRIES (CANNOT BE CHANGED IN GAME)
|
|
// You can automatically give up to 5 journal entries to DMs and up to 10 journal
|
|
// entries to players. Journal entries can be useful for documenting the specific
|
|
// rules of the game, as well as the background story so far.
|
|
// Setting the journal entry to a blank string ("") will prevent it from being given.
|
|
// A journal can have multiple entries, so you have to specify the entry ID of the
|
|
// entry you want to display.
|
|
const string DMSTART_JOURNAL_NAME_DM_1 = "";
|
|
const int DMSTART_JOURNAL_ENTRY_DM_1 = 1;
|
|
const string DMSTART_JOURNAL_NAME_DM_2 = "";
|
|
const int DMSTART_JOURNAL_ENTRY_DM_2 = 1;
|
|
const string DMSTART_JOURNAL_NAME_DM_3 = "";
|
|
const int DMSTART_JOURNAL_ENTRY_DM_3 = 1;
|
|
const string DMSTART_JOURNAL_NAME_DM_4 = "";
|
|
const int DMSTART_JOURNAL_ENTRY_DM_4 = 1;
|
|
const string DMSTART_JOURNAL_NAME_DM_5 = "";
|
|
const int DMSTART_JOURNAL_ENTRY_DM_5 = 1;
|
|
const string DMSTART_JOURNAL_NAME_PC_1 = "welcome";
|
|
const int DMSTART_JOURNAL_ENTRY_PC_1 = 1;
|
|
const string DMSTART_JOURNAL_NAME_PC_2 = "rules";
|
|
const int DMSTART_JOURNAL_ENTRY_PC_2 = 1;
|
|
const string DMSTART_JOURNAL_NAME_PC_3 = "class";
|
|
const int DMSTART_JOURNAL_ENTRY_PC_3 = 1;
|
|
const string DMSTART_JOURNAL_NAME_PC_4 = "skills";
|
|
const int DMSTART_JOURNAL_ENTRY_PC_4 = 1;
|
|
const string DMSTART_JOURNAL_NAME_PC_5 = "character";
|
|
const int DMSTART_JOURNAL_ENTRY_PC_5 = 1;
|
|
const string DMSTART_JOURNAL_NAME_PC_6 = "death";
|
|
const int DMSTART_JOURNAL_ENTRY_PC_6 = 1;
|
|
const string DMSTART_JOURNAL_NAME_PC_7 = "";
|
|
const int DMSTART_JOURNAL_ENTRY_PC_7 = 1;
|
|
const string DMSTART_JOURNAL_NAME_PC_8 = "pvp";
|
|
const int DMSTART_JOURNAL_ENTRY_PC_8 = 1;
|
|
const string DMSTART_JOURNAL_NAME_PC_9 = "horses";
|
|
const int DMSTART_JOURNAL_ENTRY_PC_9 = 1;
|
|
const string DMSTART_JOURNAL_NAME_PC_10 = "";
|
|
const int DMSTART_JOURNAL_ENTRY_PC_10 = 1;
|
|
|
|
// *****************************************************************************
|
|
// ** CONSTANTS (do not modify)
|
|
// *****************************************************************************
|
|
|
|
// LOCAL VARIABLES
|
|
const string DMSTART_INITIALIZED = "DMStartInit";
|
|
const string DMSTART_UNLOCK = "DMStartUnlock";
|
|
const string DMSTART_ITEMS_DM = "DMStartItemsDM";
|
|
const string DMSTART_ITEMS_PC = "DMStartItemsPC";
|
|
const string DMSTART_ITEMS_LANGUAGE= "DMStartItemsLanguage";
|
|
const string DMSTART_XP = "DMStartXP";
|
|
const string DMSTART_XP_BY_LEVEL = "DMStartXPByLevel";
|
|
const string DMSTART_GP = "DMStartGP";
|
|
const string DMSTART_GP_BY_LEVEL = "DMStartGPByLevel";
|
|
const string DMSTART_MERC_APPRAISE = "DMStartMercAppraise";
|
|
const string DMSTART_MERC_BUY = "DMStartMercBuy";
|
|
const string DMSTART_MERC_SELL = "DMStartMercSell";
|
|
const string DMSTART_SETTINGS_WP = "DMStartSettingsWP";
|
|
const string DMSTART_SETTINGS_NPC = "DMStartSettingsNPC";
|
|
const string DMSTART_SETTINGS_VAR = "DMStartSettingsVar";
|
|
const string DMSTART_SETTINGS_DESC = "DMStartSettingsDesc";
|
|
const string DMSTART_PROTECTION = "DMStartProtection";
|
|
|
|
// DOORS
|
|
const string DMSTART_DOOR_MERCHANT = "dmfi_start_door_merchants";
|
|
const string DMSTART_DOOR_MAGIC = "dmfi_start_door_magic";
|
|
const string DMSTART_DOOR_WEST = "dmfi_start_door_west";
|
|
const string DMSTART_DOOR_EAST = "dmfi_start_door_east";
|
|
const string DMSTART_DOOR_NORTH = "dmfi_start_door_north";
|
|
|
|
// CHESTS (STARTING ITEMS)
|
|
const string DMSTART_CHEST_DM_ONCE = "dmfi_start_chest_dm";
|
|
const string DMSTART_CHEST_PC_ONCE = "dmfi_start_chest_pc";
|
|
const string DMSTART_CHEST_PC_ALWAYS = "dmfi_start_chest_pc_always";
|
|
const string DMSTART_CHEST_PC_CLASS = "dmfi_start_chest_pc_class_";
|
|
|
|
// ITEM STRIPPING
|
|
const string DMSTART_STRIP_CHEST = "dmfi_start_stripped_items";
|
|
const string DMSTART_STRIP_TRIGGER = "dmfi_start_strip_player";
|
|
|
|
// SETTINGS
|
|
const string DMSTART_SETTINGS_NPC_TAG = "dmfi_start_area_setting_npc";
|
|
const string DMSTART_SETTINGS_WP_TAG = "dmfi_start_area_setting_wp";
|
|
|
|
// *****************************************************************************
|
|
// ** FUNCTIONS
|
|
// *****************************************************************************
|
|
|
|
// DMStartStrTok
|
|
// Returns the ith element in a , separated string. If the element
|
|
// does not exist it returns an empty string.
|
|
// sStr - the string.
|
|
// i - the ith element.
|
|
// bGetRest - if true, then get the rest of the string.
|
|
string DMStartStrTok(string sStr, int i, int bGetRest = FALSE);
|
|
string DMStartStrTok(string sStr, int i, int bGetRest = FALSE)
|
|
{
|
|
int iIndex = 1;
|
|
int iPos = GetStringLength(sStr);
|
|
int iDelimiter = FindSubString(sStr, ",");
|
|
string sMatch = "";
|
|
// Base case, list is one item long and will never enter the loop.
|
|
if (iDelimiter == -1) sMatch = sStr;
|
|
while (iDelimiter != -1)
|
|
{
|
|
// Quit the loop if we've found the item.
|
|
if (iIndex == i)
|
|
{
|
|
if (bGetRest) sMatch = GetStringRight(sStr, iPos);
|
|
else sMatch = GetStringLeft(GetStringRight(sStr, iPos), iDelimiter);
|
|
break;
|
|
}
|
|
iIndex++;
|
|
iPos = iPos - iDelimiter - 1;
|
|
iDelimiter = FindSubString(GetStringRight(sStr, iPos), ",");
|
|
// At the last item.
|
|
if (iDelimiter == -1) sMatch = GetStringRight(sStr, iPos);
|
|
}
|
|
// If we found the item we are looking for, then return it.
|
|
// Otherwise return an empty string.
|
|
if (iIndex == i) return sMatch;
|
|
else return "";
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// Get the amount of XP required for a specific level.
|
|
// iLevel - the level to get the XP for.
|
|
// Returns the amount of XP.
|
|
int DMStartGetXPForLevel (int iLevel);
|
|
int DMStartGetXPForLevel (int iLevel)
|
|
{
|
|
int i = 0;
|
|
int iXP = 0;
|
|
for (i=1; i<=iLevel; i++)
|
|
{
|
|
iXP += 1000*(i-1);
|
|
}
|
|
return iXP;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// Get the level for a specific amount of XP.
|
|
// iXP - the XP to get the level for.
|
|
// Returns the level.
|
|
int DMStartGetLevelByXP (int iXP);
|
|
int DMStartGetLevelByXP (int iXP)
|
|
{
|
|
// L1
|
|
if ((iXP >= 0) && (iXP < 1000)) return 1;
|
|
// L2
|
|
else if ((iXP >= 1000) && (iXP < 3000)) return 2;
|
|
// L3
|
|
else if ((iXP >= 3000) && (iXP < 6000)) return 3;
|
|
// L4
|
|
else if ((iXP >= 6000) && (iXP < 10000)) return 4;
|
|
// L5
|
|
else if ((iXP >= 10000) && (iXP < 15000)) return 5;
|
|
// L6
|
|
else if ((iXP >= 15000) && (iXP < 21000)) return 6;
|
|
// L7
|
|
else if ((iXP >= 21000) && (iXP < 28000)) return 7;
|
|
// L8
|
|
else if ((iXP >= 28000) && (iXP < 36000)) return 8;
|
|
// L9
|
|
else if ((iXP >= 36000) && (iXP < 45000)) return 9;
|
|
// L10
|
|
else if ((iXP >= 45000) && (iXP < 55000)) return 10;
|
|
// L11
|
|
else if ((iXP >= 55000) && (iXP < 66000)) return 11;
|
|
// L12
|
|
else if ((iXP >= 66000) && (iXP < 78000)) return 12;
|
|
// L13
|
|
else if ((iXP >= 78000) && (iXP < 91000)) return 13;
|
|
// L14
|
|
else if ((iXP >= 91000) && (iXP < 105000)) return 14;
|
|
// L15
|
|
else if ((iXP >= 105000) && (iXP < 120000)) return 15;
|
|
// L16
|
|
else if ((iXP >= 120000) && (iXP < 136000)) return 16;
|
|
// L17
|
|
else if ((iXP >= 136000) && (iXP < 153000)) return 17;
|
|
// L18
|
|
else if ((iXP >= 153000) && (iXP < 171000)) return 18;
|
|
// L19
|
|
else if ((iXP >= 171000) && (iXP < 190000)) return 19;
|
|
// L20
|
|
else if (iXP >= 190000) return 20;
|
|
return 0;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// Get the starting GP for a level 1 character by class.
|
|
// oPC - the player to get the GP for.
|
|
// Returns the starting GP for oPC.
|
|
int DMStartGetStartingGPByClass(object oPC);
|
|
int DMStartGetStartingGPByClass(object oPC)
|
|
{
|
|
if (DMSTART_AVERAGE_GP_LEVEL_1)
|
|
{
|
|
switch(GetClassByPosition(1, oPC))
|
|
{
|
|
case CLASS_TYPE_BARBARIAN: return 100;
|
|
case CLASS_TYPE_BARD: return 100;
|
|
case CLASS_TYPE_CLERIC: return 125;
|
|
case CLASS_TYPE_DRUID: return 50;
|
|
case CLASS_TYPE_FIGHTER: return 150;
|
|
case CLASS_TYPE_MONK: return 13;
|
|
case CLASS_TYPE_PALADIN: return 150;
|
|
case CLASS_TYPE_RANGER: return 150;
|
|
case CLASS_TYPE_ROGUE: return 125;
|
|
case CLASS_TYPE_SORCERER: return 75;
|
|
case CLASS_TYPE_WIZARD: return 75;
|
|
}
|
|
} else {
|
|
switch(GetClassByPosition(1, oPC))
|
|
{
|
|
case CLASS_TYPE_BARBARIAN: return 10*d4(4);
|
|
case CLASS_TYPE_BARD: return 10*d4(4);
|
|
case CLASS_TYPE_CLERIC: return 10*d4(5);
|
|
case CLASS_TYPE_DRUID: return 10*d4(2);
|
|
case CLASS_TYPE_FIGHTER: return 10*d4(6);
|
|
case CLASS_TYPE_MONK: return d4(5);
|
|
case CLASS_TYPE_PALADIN: return 10*d4(6);
|
|
case CLASS_TYPE_RANGER: return 10*d4(6);
|
|
case CLASS_TYPE_ROGUE: return 10*d4(5);
|
|
case CLASS_TYPE_SORCERER: return 10*d4(3);
|
|
case CLASS_TYPE_WIZARD: return 10*d4(3);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// Gets the amount of GP for a specific level.
|
|
// oPC - the player to get the starting GP for.
|
|
// iXP - the amount of XP (level) to get the GP for.
|
|
// The GP amount.
|
|
int DMStartGetGPForXP (object oPC, int iXP);
|
|
int DMStartGetGPForXP (object oPC, int iXP)
|
|
{
|
|
// Numbers taken from this thread:
|
|
// http://enworld.cyberstreet.com/showthread.php?t=49118
|
|
switch(DMStartGetLevelByXP(iXP))
|
|
{
|
|
case 1: return DMStartGetStartingGPByClass(oPC);
|
|
case 2: return 900;
|
|
case 3: return 2700;
|
|
case 4: return 5400;
|
|
case 5: return 9000;
|
|
case 6: return 13000;
|
|
case 7: return 19000;
|
|
case 8: return 27000;
|
|
case 9: return 36000;
|
|
case 10: return 49000;
|
|
case 11: return 66000;
|
|
case 12: return 88000;
|
|
case 13: return 110000;
|
|
case 14: return 150000;
|
|
case 15: return 200000;
|
|
case 16: return 260000;
|
|
case 17: return 340000;
|
|
case 18: return 440000;
|
|
case 19: return 580000;
|
|
case 20: return 760000;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// Initialization routine.
|
|
void DMStartInitializeState();
|
|
void DMStartInitializeState()
|
|
{
|
|
// Set up local area variables based on the default settings.
|
|
if (DMSTART_GIVE_LEVEL > 0) SetLocalInt(OBJECT_SELF, DMSTART_XP, DMStartGetXPForLevel(DMSTART_GIVE_LEVEL));
|
|
else SetLocalInt(OBJECT_SELF, DMSTART_XP, DMSTART_GIVE_XP);
|
|
if (DMSTART_GIVE_GP == -1) SetLocalInt(OBJECT_SELF, DMSTART_GP_BY_LEVEL, 1);
|
|
else SetLocalInt(OBJECT_SELF, DMSTART_GP, DMSTART_GIVE_GP);
|
|
if (DMSTART_GIVE_ITEMS_DM) SetLocalInt(OBJECT_SELF, DMSTART_ITEMS_DM, 1);
|
|
if (DMSTART_GIVE_ITEMS_PC) SetLocalInt(OBJECT_SELF, DMSTART_ITEMS_PC, 1);
|
|
if (DMSTART_GIVE_ITEMS_LANGUAGE) SetLocalInt(OBJECT_SELF, DMSTART_ITEMS_LANGUAGE, 1);
|
|
if (DMSTART_MERCHANTS_USE_APPRAISE) SetLocalInt(OBJECT_SELF, DMSTART_MERC_APPRAISE, 1);
|
|
if (DMSTART_MERCHANTS_MARK_UP_SELL) SetLocalInt(OBJECT_SELF, DMSTART_MERC_SELL, DMSTART_MERCHANTS_MARK_UP_SELL);
|
|
if (DMSTART_MERCHANTS_MARK_DOWN_BUY) SetLocalInt(OBJECT_SELF, DMSTART_MERC_BUY, DMSTART_MERCHANTS_MARK_DOWN_BUY);
|
|
|
|
// This is just a quick way to set up a variable for the tag of each door.
|
|
if (DMSTART_UNLOCK_MERCHANT) SetLocalInt(OBJECT_SELF, DMSTART_UNLOCK+DMSTART_DOOR_MERCHANT, 1);
|
|
if (DMSTART_UNLOCK_MAGIC) SetLocalInt(OBJECT_SELF, DMSTART_UNLOCK+DMSTART_DOOR_MAGIC, 1);
|
|
if (DMSTART_UNLOCK_WEST) SetLocalInt(OBJECT_SELF, DMSTART_UNLOCK+DMSTART_DOOR_WEST, 1);
|
|
if (DMSTART_UNLOCK_EAST) SetLocalInt(OBJECT_SELF, DMSTART_UNLOCK+DMSTART_DOOR_EAST, 1);
|
|
if (DMSTART_UNLOCK_NORTH) SetLocalInt(OBJECT_SELF, DMSTART_UNLOCK+DMSTART_DOOR_NORTH, 1);
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// Initialization routine.
|
|
// Initialize all of the objects in the game. This function is not called
|
|
// until a player logs in. That prevents the function from running before
|
|
// the objects it is supposed to initialize exist.
|
|
void DMStartInitializeObjects();
|
|
void DMStartInitializeObjects()
|
|
{
|
|
object oObject = GetFirstObjectInArea(OBJECT_SELF);
|
|
int iType;
|
|
while (GetIsObjectValid(oObject))
|
|
{
|
|
iType = GetObjectType(oObject);
|
|
if (iType == OBJECT_TYPE_CREATURE)
|
|
{
|
|
if (!GetIsPC(oObject))
|
|
{
|
|
if(GetTag(oObject) == DMSTART_SETTINGS_NPC_TAG)
|
|
{
|
|
// Store the settings NPC as a local object to speed up finding it.
|
|
SetLocalObject(OBJECT_SELF, DMSTART_SETTINGS_NPC, oObject);
|
|
SetListening(oObject, TRUE);
|
|
SetListenPattern(oObject, "**", 20600); //listen to all text
|
|
} else {
|
|
// Freeze all of the creatures (ie: store fronts) so that they do not
|
|
// perform ambient animations. Need a slight delay so that they do not
|
|
// get stuck equipping items.
|
|
//AssignCommand(oObject, DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectVisualEffect(VFX_DUR_FREEZE_ANIMATION), oObject)));
|
|
}
|
|
}
|
|
}
|
|
else if (iType == OBJECT_TYPE_DOOR)
|
|
{
|
|
// Checks to see if the door should be unlocked, if so then unlock it.
|
|
if (GetLocalInt(OBJECT_SELF, DMSTART_UNLOCK+GetTag(oObject)))
|
|
{
|
|
AssignCommand(oObject, SetLocked(oObject, FALSE));
|
|
AssignCommand(oObject, ActionOpenDoor(oObject));
|
|
}
|
|
}
|
|
oObject = GetNextObjectInArea(OBJECT_SELF);
|
|
}
|
|
// If no listener NPC was found, write an error.
|
|
if (!GetIsObjectValid(GetLocalObject(OBJECT_SELF, DMSTART_SETTINGS_NPC))) WriteTimestampedLogEntry("ERROR: DMFI Start Area: there is no listener NPC!");
|
|
// Find the waypoint for storing the listener NPC.
|
|
SetLocalObject(OBJECT_SELF, DMSTART_SETTINGS_WP, GetWaypointByTag(DMSTART_SETTINGS_WP_TAG));
|
|
if (!GetIsObjectValid(GetLocalObject(OBJECT_SELF, DMSTART_SETTINGS_WP))) WriteTimestampedLogEntry("ERROR: DMFI Start Area: could not find waypoint for listening NPC!");
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// Show the configuration settings.
|
|
// oArea - the DM start area.
|
|
// oPC - the DM to show the settings to.
|
|
void DMStartViewSettings (object oArea, object oPC);
|
|
void DMStartViewSettings (object oArea, object oPC)
|
|
{
|
|
string sMsg = "";
|
|
int iXP = GetLocalInt(oArea, DMSTART_XP);
|
|
int iGPByLevel = GetLocalInt(oArea, DMSTART_GP_BY_LEVEL);
|
|
int iGP = GetLocalInt(oArea, DMSTART_GP);
|
|
int iItemsDM = GetLocalInt(oArea, DMSTART_ITEMS_DM);
|
|
int iItemsPC = GetLocalInt(oArea, DMSTART_ITEMS_PC);
|
|
int iItemsLanguage = GetLocalInt(oArea, DMSTART_ITEMS_LANGUAGE);
|
|
int iMercAppraise = GetLocalInt(oArea, DMSTART_MERC_APPRAISE);
|
|
int iMercBuy = GetLocalInt(oArea, DMSTART_MERC_BUY);
|
|
int iMercSell = GetLocalInt(oArea, DMSTART_MERC_SELL);
|
|
sMsg += "Starting XP: "+IntToString(iXP)+" (Level: "+IntToString(DMStartGetLevelByXP(iXP))+")\n";
|
|
if ((iGPByLevel) && (iXP < 1000)) sMsg += "Starting Gold: by starting class\n";
|
|
else if ((iGPByLevel) && (iXP >= 1000)) sMsg += "Starting Gold: "+IntToString(DMStartGetGPForXP(oPC, iXP))+"\n";
|
|
else sMsg += "Starting Gold: "+IntToString(iGP)+"\n";
|
|
if (iMercAppraise) sMsg += "Starting merchant prices are affected by appraise.\n";
|
|
else sMsg += "Starting merchant prices are not affected by appraise.\n";
|
|
sMsg += "Starting merchants are buying for "+IntToString(100+iMercBuy)+"% of item price.\n";
|
|
sMsg += "Starting merchants are selling for "+IntToString(100+iMercSell)+"% of item price.\n";
|
|
if (iItemsDM) sMsg += "DMs are given items from the DM starting chest.\n";
|
|
if (iItemsPC) sMsg += "Players are given items from the PC starting chest.\n";
|
|
if (iItemsLanguage) sMsg += "Players are given their racial and class languages.\n";
|
|
SendMessageToPC(oPC, sMsg);
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// NOTE: This script is by Bioware and it was taken from NW_I0_PLOT. I am directly including it in
|
|
// this script to reduce dependancies and prevent compile issues for people who do not have SOU installed.
|
|
void DMStartAppraiseOpenStore(object oStore, object oPC, int nBonusMarkUp = 0, int nBonusMarkDown = 0);
|
|
void DMStartAppraiseOpenStore(object oStore, object oPC, int nBonusMarkUp = 0, int nBonusMarkDown = 0)
|
|
{
|
|
int STATE_FAILED = 1;
|
|
int STATE_TIE = 2;
|
|
int STATE_WON = 3;
|
|
string sTag = ObjectToString(OBJECT_SELF);
|
|
int nPlayerSkillRank = GetSkillRank(SKILL_APPRAISE, oPC);
|
|
int nNPCSkillRank = GetSkillRank(SKILL_APPRAISE, OBJECT_SELF);
|
|
int nAdjust = 0;
|
|
/*
|
|
New System:
|
|
|
|
An opposed skill check (a d10 roll instead). Your appraise skill versus the shopkeepers appraise skill.
|
|
|
|
Possible Results:
|
|
|
|
Percentage Rebate/Penalty: The 'difference'
|
|
|
|
Feedback: [Appraise Skill]: Merchant's reaction is unfavorable.
|
|
[Appraise Skill]: Merchant's reaction is neutral.
|
|
[Appraise Skill]: Merchant's reaction is favorable.
|
|
|
|
Additional: Remember last reaction for this particular skill.
|
|
When the player gets a new skill rank in this skill they'll get a
|
|
reroll against this merchant.
|
|
|
|
*/
|
|
|
|
int nState = 0;
|
|
int nPreviousRank = GetLocalInt(oPC, "X0_APPRAISERANK"+ sTag);
|
|
// * if the player's rank has improved, let them have another appraise check
|
|
// * against this merchant
|
|
if ( (nPlayerSkillRank > nPreviousRank) || !GetLocalInt(oPC, "X0_APPRAISEVISITED"+sTag) )
|
|
{
|
|
SetLocalInt(oPC, "X0_APPRAISERANK"+ sTag, nPlayerSkillRank);
|
|
SetLocalInt(oPC, "X0_APPRAISEVISITED"+sTag, 1);
|
|
nPlayerSkillRank = nPlayerSkillRank + d10();
|
|
nNPCSkillRank = nNPCSkillRank + d10();
|
|
nAdjust = nNPCSkillRank - nPlayerSkillRank; // * determines the level of price modification
|
|
if (nNPCSkillRank > nPlayerSkillRank)
|
|
{
|
|
nState = STATE_FAILED;
|
|
}
|
|
else
|
|
if (nNPCSkillRank < nPlayerSkillRank)
|
|
{
|
|
nState = STATE_WON;
|
|
}
|
|
else
|
|
if (nNPCSkillRank == nPlayerSkillRank)
|
|
{
|
|
nState = STATE_TIE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// * recover last reaction
|
|
nAdjust = GetLocalInt(oPC, "X0_APPRAISEADJUST" + sTag);
|
|
if (nAdjust > 0)
|
|
{
|
|
nState = STATE_FAILED;
|
|
}
|
|
else
|
|
if (nAdjust < 0)
|
|
{
|
|
nState = STATE_WON;
|
|
}
|
|
else
|
|
if (nAdjust == 0)
|
|
{
|
|
nState = STATE_TIE;
|
|
}
|
|
}
|
|
if (nState == STATE_FAILED )
|
|
{
|
|
FloatingTextStrRefOnCreature(8963, oPC, FALSE);
|
|
}
|
|
else
|
|
if (nState == STATE_WON)
|
|
{
|
|
FloatingTextStrRefOnCreature(8965, oPC, FALSE);
|
|
}
|
|
else
|
|
if (nState == STATE_TIE)
|
|
{
|
|
FloatingTextStrRefOnCreature(8964, oPC, FALSE);
|
|
}
|
|
SetLocalInt(oPC, "X0_APPRAISEADJUST"+ sTag, nAdjust);
|
|
// * Hard cap of 30% max up or down
|
|
if (nAdjust > 30)
|
|
nAdjust = 30;
|
|
if (nAdjust < -30)
|
|
nAdjust = -30;
|
|
nBonusMarkUp = nBonusMarkUp + nAdjust;
|
|
nBonusMarkDown = nBonusMarkDown - nAdjust;
|
|
OpenStore(oStore, oPC, nBonusMarkUp, nBonusMarkDown);
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// Give all the items in a comma separated list to oPC.
|
|
// oPC - the player to give the items to.
|
|
// sResRef - a comma separated list of ResRefs.
|
|
void DMStartGiveItemList (object oPC, string sResRefList);
|
|
void DMStartGiveItemList (object oPC, string sResRefList)
|
|
{
|
|
object oItem;
|
|
int i = 1;
|
|
string sResRef = DMStartStrTok(sResRefList, i);
|
|
while (sResRef != "")
|
|
{
|
|
if (!GetIsObjectValid( GetItemPossessedBy(oPC, sResRef) ))
|
|
{
|
|
oItem = CreateItemOnObject(sResRef, oPC);
|
|
if (!GetIsObjectValid(oItem)) WriteTimestampedLogEntry("ERROR: dmfi_start_area could not create item with ResRef: "+sResRef);
|
|
}
|
|
i++;
|
|
sResRef = DMStartStrTok(sResRefList, i);
|
|
}
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// Give a player the DMFI Voice language widgets they are entitled to.
|
|
// oPC - the player to give the language widgets to.
|
|
void DMStartGiveLanguages(object oPC);
|
|
void DMStartGiveLanguages(object oPC)
|
|
{
|
|
string sList = "";
|
|
if (MyPRCGetRacialType(oPC) == RACIAL_TYPE_DWARF)
|
|
{
|
|
if (sList != "") sList += ",";
|
|
sList += "hlslang_4";
|
|
}
|
|
if (MyPRCGetRacialType(oPC) == RACIAL_TYPE_ELF)
|
|
{
|
|
if (sList != "") sList += ",";
|
|
sList += "hlslang_1";
|
|
}
|
|
if (MyPRCGetRacialType(oPC) == RACIAL_TYPE_HALFELF)
|
|
{
|
|
if (sList != "") sList += ",";
|
|
sList += "hlslang_1";
|
|
}
|
|
if (MyPRCGetRacialType(oPC) == RACIAL_TYPE_GNOME)
|
|
{
|
|
if (sList != "") sList += ",";
|
|
sList += "hlslang_2";
|
|
}
|
|
if (MyPRCGetRacialType(oPC) == RACIAL_TYPE_HALFLING)
|
|
{
|
|
if (sList != "") sList += ",";
|
|
sList += "hlslang_3";
|
|
}
|
|
if (MyPRCGetRacialType(oPC) == RACIAL_TYPE_HALFORC)
|
|
{
|
|
if (sList != "") sList += ",";
|
|
sList += "hlslang_5";
|
|
}
|
|
if (GetLevelByClass(CLASS_TYPE_DRUID, oPC) || GetLevelByClass(CLASS_TYPE_RANGER, oPC))
|
|
{
|
|
if (sList != "") sList += ",";
|
|
sList += "hlslang_8";
|
|
}
|
|
if (GetLevelByClass(CLASS_TYPE_ROGUE, oPC))
|
|
{
|
|
if (sList != "") sList += ",";
|
|
sList += "hlslang_9";
|
|
}
|
|
// Now that the list specific to this player is build, process it.
|
|
// Note: if the blueprints do not exist then the items will not be created.
|
|
DMStartGiveItemList(oPC, sList);
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// Give starting items from a chest to a player.
|
|
// oPC - the player to give items to.
|
|
// sTag - the tag of the chest containing the starting items.
|
|
// bOnlyOne - if true, then only give them the item if they do not already possess it.
|
|
void DMStartGiveItems(object oPC, string sTag, int bOnlyOne = TRUE);
|
|
void DMStartGiveItems(object oPC, string sTag, int bOnlyOne = TRUE)
|
|
{
|
|
object oChest = GetNearestObjectByTag(sTag);
|
|
object oItem;
|
|
object oNewItem;
|
|
// Try to find the chest with the items.
|
|
if (!GetIsObjectValid(oChest))
|
|
{
|
|
WriteTimestampedLogEntry("ERROR: dmfi_start_area could not find placeable with Tag: "+sTag);
|
|
return;
|
|
}
|
|
if (bOnlyOne)
|
|
{
|
|
oItem = GetFirstItemInInventory(oChest);
|
|
while (GetIsObjectValid(oItem))
|
|
{
|
|
// Only give items to players if they do not already have them.
|
|
if (!GetIsObjectValid( GetItemPossessedBy(oPC, GetTag(oItem)) ))
|
|
{
|
|
oNewItem = CopyItem(oItem, oPC);
|
|
// If this item is armor, and the player has no armor, then try
|
|
// to equip it.
|
|
if (GetBaseItemType(oNewItem) == BASE_ITEM_ARMOR)
|
|
{
|
|
if (!GetIsObjectValid( GetItemInSlot(INVENTORY_SLOT_CHEST, oPC) ))
|
|
{
|
|
AssignCommand(oPC, ActionEquipItem(oNewItem, INVENTORY_SLOT_CHEST));
|
|
}
|
|
}
|
|
} else {
|
|
SendMessageToPC(oPC, "You already have "+GetTag(oItem));
|
|
}
|
|
oItem = GetNextItemInInventory(oChest);
|
|
}
|
|
} else {
|
|
oItem = GetFirstItemInInventory(oChest);
|
|
while (GetIsObjectValid(oItem))
|
|
{
|
|
// Always give items to players.
|
|
oNewItem = CopyItem(oItem, oPC);
|
|
// If this item is armor, and the player has no armor, then try
|
|
// to equip it.
|
|
if (GetBaseItemType(oNewItem) == BASE_ITEM_ARMOR)
|
|
{
|
|
if (!GetIsObjectValid( GetItemInSlot(INVENTORY_SLOT_CHEST, oPC) ))
|
|
{
|
|
AssignCommand(oPC, ActionEquipItem(oNewItem, INVENTORY_SLOT_CHEST));
|
|
}
|
|
}
|
|
oItem = GetNextItemInInventory(oChest);
|
|
}
|
|
}
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// Strip a player of all their items/gold and give them the amount of gold they
|
|
// are supposed to have as well as the starting items.
|
|
// oArea - the DMFI DM Start Area.
|
|
// oPC - the player to strip the items from.
|
|
void DMStartStripPlayer (object oArea, object oPC);
|
|
void DMStartStripPlayer (object oArea, object oPC)
|
|
{
|
|
// Do not attempt to strip DMs!
|
|
if (!GetIsPC(oPC) || GetIsDM(oPC) || GetIsDMPossessed(oPC)) return;
|
|
// Try to find the chest for storing the stripped items.
|
|
object oChest = GetNearestObjectByTag(DMSTART_STRIP_CHEST);
|
|
if (!GetIsObjectValid(oChest))
|
|
{
|
|
WriteTimestampedLogEntry("ERROR: dmfi_start_area could not find placeable with Tag: "+DMSTART_STRIP_CHEST);
|
|
return;
|
|
}
|
|
SendMessageToPC(oPC, "Removing items.");
|
|
// Destroy gold.
|
|
TakeGoldFromCreature(GetGold(oPC), oPC, TRUE);
|
|
// Remove the equipped items.
|
|
object oItem;
|
|
int i;
|
|
for(i=0; i < NUM_INVENTORY_SLOTS; i++)
|
|
{
|
|
oItem = GetItemInSlot(i, oPC);
|
|
if (GetIsObjectValid(oItem))
|
|
{
|
|
CopyItem(oItem, oChest);
|
|
DestroyObject(oItem);
|
|
}
|
|
}
|
|
// Remove the inventory items.
|
|
oItem = GetFirstItemInInventory(oPC);
|
|
while (GetIsObjectValid(oItem))
|
|
{
|
|
CopyItem(oItem, oChest);
|
|
DestroyObject(oItem);
|
|
oItem = GetNextItemInInventory(oPC);
|
|
}
|
|
// Give them the starting GP.
|
|
int iGPByLevel = GetLocalInt(oArea, DMSTART_GP_BY_LEVEL);
|
|
int iGP = GetLocalInt(oArea, DMSTART_GP);
|
|
if (iGPByLevel) iGP = DMStartGetGPForXP(oPC, GetXP(oPC));
|
|
GiveGoldToCreature(oPC, iGP);
|
|
SendMessageToAllDMs(GetName(oPC)+" was given "+IntToString(iGP)+" starting gold.");
|
|
// Give them the player starting items.
|
|
// Items that are given to the player only if they don't possess them.
|
|
if (GetLocalInt(oArea, DMSTART_ITEMS_PC)) AssignCommand(oPC, DMStartGiveItems(oPC, DMSTART_CHEST_PC_ONCE));
|
|
// Items that are always given to the player.
|
|
if (GetLocalInt(oArea, DMSTART_ITEMS_PC)) AssignCommand(oPC, DMStartGiveItems(oPC, DMSTART_CHEST_PC_ALWAYS, FALSE));
|
|
// Items that are always given to the player by class.
|
|
if (GetLocalInt(oArea, DMSTART_ITEMS_PC)) AssignCommand(oPC, DMStartGiveItems(oPC, DMSTART_CHEST_PC_CLASS+IntToString(GetClassByPosition(1, oPC)), FALSE));
|
|
// Give them the player language items.
|
|
if (GetLocalInt(oArea, DMSTART_ITEMS_LANGUAGE)) AssignCommand(oPC, DMStartGiveLanguages(oPC));
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// Give a player/DM the automatic journals.
|
|
// oPC - the player to give the journals to.
|
|
void DMStartGiveJournals (object oPC);
|
|
void DMStartGiveJournals (object oPC)
|
|
{
|
|
if (GetIsDM(oPC) || GetIsDMPossessed(oPC))
|
|
{
|
|
// Is a DM.
|
|
if (DMSTART_JOURNAL_NAME_DM_1 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_DM_1, DMSTART_JOURNAL_ENTRY_DM_1, oPC, FALSE, FALSE, TRUE);
|
|
if (DMSTART_JOURNAL_NAME_DM_2 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_DM_2, DMSTART_JOURNAL_ENTRY_DM_2, oPC, FALSE, FALSE, TRUE);
|
|
if (DMSTART_JOURNAL_NAME_DM_3 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_DM_3, DMSTART_JOURNAL_ENTRY_DM_3, oPC, FALSE, FALSE, TRUE);
|
|
if (DMSTART_JOURNAL_NAME_DM_4 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_DM_4, DMSTART_JOURNAL_ENTRY_DM_4, oPC, FALSE, FALSE, TRUE);
|
|
if (DMSTART_JOURNAL_NAME_DM_5 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_DM_5, DMSTART_JOURNAL_ENTRY_DM_5, oPC, FALSE, FALSE, TRUE);
|
|
return;
|
|
} else {
|
|
// Is a player.
|
|
if (DMSTART_JOURNAL_NAME_PC_1 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_PC_1, DMSTART_JOURNAL_ENTRY_PC_1, oPC, FALSE, FALSE, TRUE);
|
|
if (DMSTART_JOURNAL_NAME_PC_2 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_PC_2, DMSTART_JOURNAL_ENTRY_PC_2, oPC, FALSE, FALSE, TRUE);
|
|
if (DMSTART_JOURNAL_NAME_PC_3 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_PC_3, DMSTART_JOURNAL_ENTRY_PC_3, oPC, FALSE, FALSE, TRUE);
|
|
if (DMSTART_JOURNAL_NAME_PC_4 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_PC_4, DMSTART_JOURNAL_ENTRY_PC_4, oPC, FALSE, FALSE, TRUE);
|
|
if (DMSTART_JOURNAL_NAME_PC_5 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_PC_5, DMSTART_JOURNAL_ENTRY_PC_5, oPC, FALSE, FALSE, TRUE);
|
|
if (DMSTART_JOURNAL_NAME_PC_6 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_PC_6, DMSTART_JOURNAL_ENTRY_PC_6, oPC, FALSE, FALSE, TRUE);
|
|
if (DMSTART_JOURNAL_NAME_PC_7 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_PC_7, DMSTART_JOURNAL_ENTRY_PC_7, oPC, FALSE, FALSE, TRUE);
|
|
if (DMSTART_JOURNAL_NAME_PC_8 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_PC_8, DMSTART_JOURNAL_ENTRY_PC_8, oPC, FALSE, FALSE, TRUE);
|
|
if (DMSTART_JOURNAL_NAME_PC_9 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_PC_9, DMSTART_JOURNAL_ENTRY_PC_9, oPC, FALSE, FALSE, TRUE);
|
|
if (DMSTART_JOURNAL_NAME_PC_10 != "") AddJournalQuestEntry(DMSTART_JOURNAL_NAME_PC_10, DMSTART_JOURNAL_ENTRY_PC_10, oPC, FALSE, FALSE, TRUE);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// Handle a player/DM that just entered the area.
|
|
// oArea - the DMFI DM Start Area
|
|
// oPC - the player who just entered.
|
|
void DMStartHandlePlayers (object oArea, object oPC);
|
|
void DMStartHandlePlayers (object oArea, object oPC)
|
|
{
|
|
// Give the journals.
|
|
DMStartGiveJournals(oPC);
|
|
// If this is a DM, give them their items and quit.
|
|
if (GetIsDM(oPC) || GetIsDMPossessed(oPC))
|
|
{
|
|
// Give them the DM Items
|
|
if (GetLocalInt(oArea, DMSTART_ITEMS_DM)) AssignCommand(oPC, DMStartGiveItems(oPC, DMSTART_CHEST_DM_ONCE));
|
|
// Tell the DM the current settings.
|
|
AssignCommand(oPC, DMStartViewSettings(oArea, oPC));
|
|
return;
|
|
}
|
|
// This is a player.
|
|
// Give new players the XP/GP and strip their items.
|
|
if (GetXP(oPC) == 0)
|
|
{
|
|
// Set the XP for the player. Always add 1 XP to keep DMs from setting players
|
|
// at zero XP so that they keep getting restripped when the log in.
|
|
int iXP = GetLocalInt(oArea, DMSTART_XP) + 1;
|
|
SetXP(oPC, iXP);
|
|
SendMessageToAllDMs(GetName(oPC)+" was given "+IntToString(iXP)+" starting experience.");
|
|
// Strip new characters. These prevents people who are trying to hack their
|
|
// starting kit by modifying 2DAs in their override directory.
|
|
AssignCommand(oPC, DMStartStripPlayer(oArea, oPC));
|
|
}
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// A DM has just toggled a boolean setting.
|
|
// oArea - the DM start area.
|
|
// oPC - the DM.
|
|
// sInt - the name of the LocalInt variable on oArea.
|
|
// sDesc - a description of the variable.
|
|
void DMStartControlToggle(object oArea, object oPC, string sInt, string sDesc);
|
|
void DMStartControlToggle(object oArea, object oPC, string sInt, string sDesc)
|
|
{
|
|
string sDir = "";
|
|
if (GetLocalInt(oArea, sInt) == 0)
|
|
{
|
|
sDir = "On";
|
|
SetLocalInt(oArea, sInt, 1);
|
|
} else {
|
|
sDir = "Off";
|
|
SetLocalInt(oArea, sInt, 0);
|
|
}
|
|
SendMessageToAllDMs(GetName(oPC)+" has turned "+sDir+" "+sDesc);
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// A DM would like to change an integer setting. Summon a listener NPC so that they
|
|
// can speak the setting outloud.
|
|
// oArea - the DM start area.
|
|
// oPC - the DM.
|
|
// sInt - the name of the LocalInt variable on oArea.
|
|
// sDesc - a description of the variable.
|
|
void DMStartControlSetting(object oArea, object oPC, string sInt, string sDesc);
|
|
void DMStartControlSetting(object oArea, object oPC, string sInt, string sDesc)
|
|
{
|
|
object oListener = GetLocalObject(oArea, DMSTART_SETTINGS_NPC);
|
|
if (!GetIsObjectValid(oListener))
|
|
{
|
|
SendMessageToPC(oPC, "ERROR: Could not find listener NPC");
|
|
WriteTimestampedLogEntry("ERROR: DMFI Start Area: could not find listener NPC");
|
|
return;
|
|
}
|
|
SetLocalString(oPC, DMSTART_SETTINGS_VAR, sInt);
|
|
SetLocalString(oPC, DMSTART_SETTINGS_DESC, sDesc);
|
|
AssignCommand(oListener, JumpToObject(oPC));
|
|
DelayCommand(0.1, AssignCommand(oListener, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_PARALYZE_HOLD), oListener, 3.0)));
|
|
DelayCommand(0.2, AssignCommand(oListener, ActionSpeakString("Appear and speak a number to change "+sDesc)));
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// A DM would like to reset the XP for all of the players in the area.
|
|
// oArea - the DM start area.
|
|
// oPC - the DM.
|
|
int DMStartControlResetXP (object oArea, object oPC);
|
|
int DMStartControlResetXP (object oArea, object oPC)
|
|
{
|
|
if (GetLocalInt(OBJECT_SELF, DMSTART_PROTECTION) == 0)
|
|
{
|
|
SetLocalInt(OBJECT_SELF, DMSTART_PROTECTION, 1);
|
|
FloatingTextStringOnCreature("Pull lever again if you are sure you want to reset XP for all players in area.", oPC, FALSE);
|
|
DelayCommand(15.0, DeleteLocalInt(OBJECT_SELF, DMSTART_PROTECTION));
|
|
return FALSE;
|
|
}
|
|
int iXP = GetLocalInt(oArea, DMSTART_XP);
|
|
SendMessageToAllDMs(GetName(oPC)+" is reseting the XP for all players in starting area.");
|
|
object oPlayer = GetFirstPC();
|
|
while (GetIsObjectValid(oPlayer))
|
|
{
|
|
if ((!GetIsDM(oPlayer)) && (!GetIsDMPossessed(oPlayer)))
|
|
{
|
|
SetXP(oPlayer, iXP);
|
|
}
|
|
oPlayer = GetNextPC();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// A DM would like to reset the GP/items for all of the players in the area.
|
|
// oArea - the DM start area.
|
|
// oPC - the DM.
|
|
int DMStartControlResetGPItems (object oArea, object oPC);
|
|
int DMStartControlResetGPItems (object oArea, object oPC)
|
|
{
|
|
if (GetLocalInt(OBJECT_SELF, DMSTART_PROTECTION) == 0)
|
|
{
|
|
SetLocalInt(OBJECT_SELF, DMSTART_PROTECTION, 1);
|
|
FloatingTextStringOnCreature("Pull lever again if you are sure you want to reset gp/items for all players in area.", oPC, FALSE);
|
|
DelayCommand(15.0, DeleteLocalInt(OBJECT_SELF, DMSTART_PROTECTION));
|
|
return FALSE;
|
|
}
|
|
SendMessageToAllDMs(GetName(oPC)+" is reseting the GP/items for all players in starting area.");
|
|
object oPlayer = GetFirstPC();
|
|
while (GetIsObjectValid(oPlayer))
|
|
{
|
|
if ((!GetIsDM(oPlayer)) && (!GetIsDMPossessed(oPlayer)))
|
|
{
|
|
AssignCommand(oPlayer, DMStartStripPlayer(oArea, oPlayer));
|
|
}
|
|
oPlayer = GetNextPC();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// A DM would like to "top up" the GP for all of the players in the area.
|
|
// oArea - the DM start area.
|
|
// oPC - the DM.
|
|
int DMStartControlTopUpGP (object oArea, object oPC);
|
|
int DMStartControlTopUpGP (object oArea, object oPC)
|
|
{
|
|
if (GetLocalInt(OBJECT_SELF, DMSTART_PROTECTION) == 0)
|
|
{
|
|
SetLocalInt(OBJECT_SELF, DMSTART_PROTECTION, 1);
|
|
FloatingTextStringOnCreature("Pull lever again if you are sure you want to top up GP for all players in area.", oPC, FALSE);
|
|
DelayCommand(15.0, DeleteLocalInt(OBJECT_SELF, DMSTART_PROTECTION));
|
|
return FALSE;
|
|
}
|
|
int iGPByLevel = GetLocalInt(oArea, DMSTART_GP_BY_LEVEL);
|
|
SendMessageToAllDMs(GetName(oPC)+" is topping up the GP for all players in starting area.");
|
|
object oPlayer = GetFirstPC();
|
|
int iGP;
|
|
int i;
|
|
object oItem;
|
|
while (GetIsObjectValid(oPlayer))
|
|
{
|
|
if ((!GetIsDM(oPlayer)) && (!GetIsDMPossessed(oPlayer)))
|
|
{
|
|
// Get the GP value the player should have.
|
|
int iGPShouldHave = GetLocalInt(oArea, DMSTART_GP);
|
|
if (iGPByLevel) iGPShouldHave = DMStartGetGPForXP(oPC, GetXP(oPC));
|
|
// Get the GP value of the player.
|
|
iGP = GetGold(oPlayer);
|
|
for(i=0; i < NUM_INVENTORY_SLOTS; i++)
|
|
{
|
|
oItem = GetItemInSlot(i, oPlayer);
|
|
if (GetIsObjectValid(oItem))
|
|
{
|
|
iGP += GetGoldPieceValue(oItem);
|
|
}
|
|
}
|
|
oItem = GetFirstItemInInventory(oPlayer);
|
|
while (GetIsObjectValid(oItem))
|
|
{
|
|
iGP += GetGoldPieceValue(oItem);
|
|
oItem = GetNextItemInInventory(oPlayer);
|
|
}
|
|
if (iGPShouldHave == iGP) SendMessageToPC(oPC, GetName(oPlayer)+" has "+IntToString(iGP)+" GP (correct amount).");
|
|
if (iGPShouldHave > iGP) SendMessageToPC(oPC, GetName(oPlayer)+" has "+IntToString(iGP)+" GP (over by "+IntToString(iGP - iGPShouldHave)+").");
|
|
if (iGPShouldHave < iGP)
|
|
{
|
|
GiveGoldToCreature(oPlayer, iGPShouldHave - iGP);
|
|
SendMessageToPC(oPC, GetName(oPlayer)+" now has "+IntToString(iGPShouldHave)+" GP (given "+IntToString(iGPShouldHave - iGP)+").");
|
|
}
|
|
}
|
|
oPlayer = GetNextPC();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// A DM would like to view the xp/gp for all of the players in the area.
|
|
// oArea - the DM start area.
|
|
// oPC - the DM.
|
|
int DMStartControlViewXPGP (object oArea, object oPC);
|
|
int DMStartControlViewXPGP (object oArea, object oPC)
|
|
{
|
|
int iXP;
|
|
int iGP;
|
|
int i;
|
|
object oItem;
|
|
object oPlayer = GetFirstPC();
|
|
while (GetIsObjectValid(oPlayer))
|
|
{
|
|
if ((!GetIsDM(oPlayer)) && (!GetIsDMPossessed(oPlayer)))
|
|
{
|
|
iXP = GetXP(oPlayer);
|
|
// Get the GP value of the player.
|
|
iGP = GetGold(oPlayer);
|
|
for(i=0; i < NUM_INVENTORY_SLOTS; i++)
|
|
{
|
|
oItem = GetItemInSlot(i, oPlayer);
|
|
if (GetIsObjectValid(oItem))
|
|
{
|
|
iGP += GetGoldPieceValue(oItem);
|
|
}
|
|
}
|
|
oItem = GetFirstItemInInventory(oPlayer);
|
|
while (GetIsObjectValid(oItem))
|
|
{
|
|
iGP += GetGoldPieceValue(oItem);
|
|
oItem = GetNextItemInInventory(oPlayer);
|
|
}
|
|
SendMessageToPC(oPC, GetName(oPlayer)+" has "+IntToString(iXP)+" XP and items totalling "+IntToString(iGP)+" GP.");
|
|
}
|
|
oPlayer = GetNextPC();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// oPC has used a placeable. Handle the placeable based on its tag.
|
|
// oArea - the DM start area.
|
|
// oPC - the person who used the placeable.
|
|
void DMStartHandlePlaceable (object oArea, object oPC);
|
|
void DMStartHandlePlaceable (object oArea, object oPC)
|
|
{
|
|
string sTag = GetTag(OBJECT_SELF);
|
|
if (sTag == "dmfi_start_sit_chair")
|
|
{
|
|
object oChair = OBJECT_SELF;
|
|
AssignCommand(oPC, ActionSit(oChair));
|
|
return;
|
|
}
|
|
if (sTag == "dmfi_start_sit_dm_chair")
|
|
{
|
|
if (!GetIsDM(oPC)) return;
|
|
object oChair = OBJECT_SELF;
|
|
AssignCommand(oPC, ActionSit(oChair));
|
|
return;
|
|
}
|
|
else if (sTag == "dmfi_start_control_view") DMStartViewSettings(oArea, oPC);
|
|
else if (sTag == "dmfi_start_control_view_players") DMStartControlViewXPGP(oArea, oPC);
|
|
else if (sTag == "dmfi_start_toggle_chest_dm") DMStartControlToggle(oArea, oPC, DMSTART_ITEMS_DM, "giving items to DMs on login.");
|
|
else if (sTag == "dmfi_start_toggle_chest_pc") DMStartControlToggle(oArea, oPC, DMSTART_ITEMS_PC, "giving items to new players on login.");
|
|
else if (sTag == "dmfi_start_toggle_chest_language") DMStartControlToggle(oArea, oPC, DMSTART_ITEMS_LANGUAGE, "giving DMFI Voice languages to new players on login.");
|
|
else if (sTag == "dmfi_start_toggle_merc_appraise") DMStartControlToggle(oArea, oPC, DMSTART_MERC_APPRAISE, "starting merchant prices affected by Appraise skill.");
|
|
else if (sTag == "dmfi_start_toggle_merc_buy") DMStartControlSetting(oArea, oPC, DMSTART_MERC_BUY, "starting merchant prices for buying items");
|
|
else if (sTag == "dmfi_start_toggle_merc_sell") DMStartControlSetting(oArea, oPC, DMSTART_MERC_SELL, "starting merchant prices for selling items");
|
|
else if (sTag == "dmfi_start_toggle_gp_by_level") DMStartControlToggle(oArea, oPC, DMSTART_GP_BY_LEVEL, "GP based off of character level.");
|
|
else if (sTag == "dmfi_start_toggle_gp") DMStartControlSetting(oArea, oPC, DMSTART_GP, "GP given to new players");
|
|
else if (sTag == "dmfi_start_toggle_xp_by_level") DMStartControlSetting(oArea, oPC, DMSTART_XP_BY_LEVEL, "level given to new players");
|
|
else if (sTag == "dmfi_start_toggle_xp") DMStartControlSetting(oArea, oPC, DMSTART_XP, "XP given to new players");
|
|
else if (sTag == "dmfi_start_control_reset_xp")
|
|
{
|
|
if (DMStartControlResetXP(oArea, oPC) == FALSE) return;
|
|
}
|
|
else if (sTag == "dmfi_start_control_reset_gp_item")
|
|
{
|
|
if (DMStartControlResetGPItems(oArea, oPC) == FALSE) return;
|
|
}
|
|
else if (sTag == "dmfi_start_control_top_up_gp")
|
|
{
|
|
if (DMStartControlTopUpGP(oArea, oPC) == FALSE) return;
|
|
}
|
|
else
|
|
{
|
|
WriteTimestampedLogEntry("ERROR: DMFI Start Area: unknown placeable with Tag "+sTag);
|
|
return;
|
|
}
|
|
PlayAnimation (ANIMATION_PLACEABLE_DEACTIVATE);
|
|
DelayCommand(1.5, PlayAnimation (ANIMATION_PLACEABLE_ACTIVATE));
|
|
PlaySound("as_sw_metalop1");
|
|
}
|
|
|
|
// *****************************************************************************
|
|
|
|
// The listener NPC has heard something. Process what it heard. This NPC is used
|
|
// to get integers from the DMs.
|
|
// oArea - the DM start area.
|
|
void DMStartListener (object oArea);
|
|
void DMStartListener (object oArea)
|
|
{
|
|
string sSaid;
|
|
string sVar;
|
|
string sDesc;
|
|
|
|
int nMatch = GetListenPatternNumber();
|
|
object oShouter = GetLastSpeaker();
|
|
if (nMatch == 20600 && GetIsObjectValid(oShouter) && GetIsDM(oShouter))
|
|
{
|
|
sSaid = GetMatchedSubstring(0);
|
|
sVar = GetLocalString(oShouter, DMSTART_SETTINGS_VAR);
|
|
sDesc = GetLocalString(oShouter, DMSTART_SETTINGS_DESC);
|
|
int iValue = StringToInt(sSaid);
|
|
SetLocalInt(oArea, sVar, iValue);
|
|
// Sanity checking on the inputs.
|
|
if (sVar == DMSTART_XP_BY_LEVEL)
|
|
{
|
|
if ((iValue < 1) || (iValue > 20))
|
|
{
|
|
SpeakString(IntToString(iValue)+" is not a valid level. (1-20)");
|
|
return;
|
|
}
|
|
// Special case, this variable doesn't really do anything. It acts
|
|
// as a wrapper for another variable.
|
|
SetLocalInt(oArea, DMSTART_XP, DMStartGetXPForLevel(iValue));
|
|
sVar = DMSTART_XP;
|
|
}
|
|
else if ((sVar == DMSTART_MERC_BUY) || (sVar == DMSTART_MERC_SELL))
|
|
{
|
|
if ((iValue < -100) || (iValue > 100))
|
|
{
|
|
SpeakString(IntToString(iValue)+" is not a valid value. (-100 to 100)");
|
|
return;
|
|
}
|
|
}
|
|
DeleteLocalString(oShouter, DMSTART_SETTINGS_VAR);
|
|
DeleteLocalString(oShouter, DMSTART_SETTINGS_DESC);
|
|
if (sVar == DMSTART_XP)
|
|
{
|
|
SendMessageToAllDMs(GetName(oShouter)+" changed " + sDesc + " to " + IntToString(GetLocalInt(oArea, sVar))+" XP (Level: "+IntToString(DMStartGetLevelByXP(GetLocalInt(oArea, sVar)))+")");
|
|
}
|
|
else if (sVar == DMSTART_GP)
|
|
{
|
|
string sMsg;
|
|
int iXP = GetLocalInt(oArea, DMSTART_XP);
|
|
int iGPByLevel = GetLocalInt(oArea, DMSTART_GP_BY_LEVEL);
|
|
int iGP = GetLocalInt(oArea, DMSTART_GP);
|
|
if ((iGPByLevel) && (iXP < 1000)) sMsg += "Starting Gold: by starting class\n";
|
|
else if ((iGPByLevel) && (iXP >= 1000)) sMsg += "Starting Gold: "+IntToString(DMStartGetGPForXP(oShouter, iXP))+"\n";
|
|
else sMsg += "Starting Gold: "+IntToString(iGP)+"\n";
|
|
SendMessageToAllDMs(GetName(oShouter)+" changed " + sDesc + " to "+sMsg);
|
|
}
|
|
else if ((sVar == DMSTART_MERC_BUY) || (sVar == DMSTART_MERC_SELL))
|
|
{
|
|
SendMessageToAllDMs(GetName(oShouter)+" changed " + sDesc + " to " + IntToString(GetLocalInt(oArea, sVar)+100)+"% of base price.");
|
|
}
|
|
else SendMessageToAllDMs(GetName(oShouter)+" changed " + sDesc + " to " + IntToString(GetLocalInt(oArea, sVar)));
|
|
DelayCommand(1.5, AssignCommand(OBJECT_SELF, ActionJumpToObject(GetLocalObject(oArea, DMSTART_SETTINGS_WP))));
|
|
}
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// ** MAIN
|
|
// *****************************************************************************
|
|
|
|
void main()
|
|
{
|
|
// NOTE: The Area OnEnter event fires for all creatures that are spawned in
|
|
// that area!
|
|
object oMod = GetModule();
|
|
object oPC = GetEnteringObject();
|
|
|
|
// If we are not initialized, then initialize.
|
|
if (GetLocalInt(oMod, DMSTART_INITIALIZED) == 0)
|
|
{
|
|
// Only run when the first player logs in.
|
|
if(GetIsPC(oPC))
|
|
{
|
|
SetLocalInt(oMod, DMSTART_INITIALIZED, 1);
|
|
PrintString("Initializing DMFI DM Start Area");
|
|
// Initialize the state right away.
|
|
DMStartInitializeState();
|
|
// Initialize the objects when done processing the new creature.
|
|
AssignCommand(OBJECT_SELF, DMStartInitializeObjects());
|
|
} else {
|
|
// A creature is calling this script when it spawns in.
|
|
return;
|
|
}
|
|
}
|
|
|
|
// There is a listen NPC that let's DMs configure settings to anything they want.
|
|
if (GetTag(OBJECT_SELF) == DMSTART_SETTINGS_NPC_TAG)
|
|
{
|
|
DMStartListener(GetArea(OBJECT_SELF));
|
|
return;
|
|
}
|
|
|
|
// Players can be stripped of items when they log in with 0XP or it can
|
|
// manually be done by the DM by jumping them to a trigger.
|
|
if (GetTag(OBJECT_SELF) == DMSTART_STRIP_TRIGGER)
|
|
{
|
|
AssignCommand(oPC, DMStartStripPlayer(GetArea(OBJECT_SELF), oPC));
|
|
return;
|
|
}
|
|
|
|
// If a player has entered the area, then handle them.
|
|
if (GetIsPC(oPC) || GetIsDM(oPC) || GetIsDMPossessed(oPC))
|
|
{
|
|
AssignCommand(OBJECT_SELF, DMStartHandlePlayers(OBJECT_SELF, oPC));
|
|
return;
|
|
}
|
|
|
|
int iObjectType = GetObjectType(OBJECT_SELF);
|
|
if (iObjectType == OBJECT_TYPE_CREATURE)
|
|
{
|
|
// Running on a merchant.
|
|
oPC = GetLastSpeaker();
|
|
object oArea = GetArea(OBJECT_SELF);
|
|
object oStore = GetNearestObjectByTag(GetTag(OBJECT_SELF));
|
|
if (GetLocalInt(oArea, DMSTART_MERC_APPRAISE)) DMStartAppraiseOpenStore(oStore, oPC, GetLocalInt(oArea, DMSTART_MERC_SELL), GetLocalInt(oArea, DMSTART_MERC_BUY));
|
|
else OpenStore(oStore, oPC, GetLocalInt(oArea, DMSTART_MERC_SELL), GetLocalInt(oArea, DMSTART_MERC_BUY));
|
|
return;
|
|
}
|
|
else if (iObjectType == OBJECT_TYPE_PLACEABLE)
|
|
{
|
|
DMStartHandlePlaceable(GetArea(OBJECT_SELF), GetLastUsedBy());
|
|
|
|
CreateItemOnObject("x3_it_pchide ", oPC);
|
|
}
|
|
}
|