Merge branch 'nightly' into ragemp
This commit is contained in:
@@ -1,15 +1,213 @@
|
||||
// ===========================================================================
|
||||
// Vortrex's Roleplay Resource
|
||||
// https://github.com/VortrexFTW/gtac_roleplay
|
||||
// Asshat Gaming Roleplay
|
||||
// https://github.com/VortrexFTW/agrp_main
|
||||
// (c) 2022 Asshat Gaming
|
||||
// ===========================================================================
|
||||
// FILE: npc.js
|
||||
// DESC: Provides NPC usage and functions
|
||||
// TYPE: Server (JavaScript)
|
||||
// ===========================================================================
|
||||
|
||||
// NPC Trigger Condition Match Types
|
||||
const AGRP_NPC_COND_MATCH_NONE = 0; // None (invalid)
|
||||
const AGRP_NPC_COND_MATCH_EQ = 1; // Must be equal to
|
||||
const AGRP_NPC_COND_MATCH_GT = 2; // Must be greater than
|
||||
const AGRP_NPC_COND_MATCH_LT = 3; // Must be less than
|
||||
const AGRP_NPC_COND_MATCH_GTEQ = 4; // Must be greater than or equal to
|
||||
const AGRP_NPC_COND_MATCH_LTEQ = 5; // Must be less than or equal to
|
||||
const AGRP_NPC_COND_MATCH_CONTAINS = 6; // Must contain string (case insensitive)
|
||||
const AGRP_NPC_COND_MATCH_CONTAINS_CASE = 7; // Must contain string (case sensitive)
|
||||
const AGRP_NPC_COND_MATCH_EXACT = 8; // Must match string exactly (case insensitive)
|
||||
const AGRP_NPC_COND_MATCH_EXACT_CASE = 9; // Must match string exactly (case insensitive)
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
// NPC Owner Types
|
||||
const AGRP_NPC_OWNER_NONE = 0; // Not owned
|
||||
const AGRP_NPC_OWNER_PLAYER = 1; // Owned by a player (character/subaccount)
|
||||
const AGRP_NPC_OWNER_JOB = 2; // Owned by a job
|
||||
const AGRP_NPC_OWNER_CLAN = 3; // Owned by a clan
|
||||
const AGRP_NPC_OWNER_FACTION = 4; // Owned by a faction (not used at the moment)
|
||||
const AGRP_NPC_OWNER_PUBLIC = 5; // Public NPC. Anybody can do stuff with it.
|
||||
const AGRP_NPC_OWNER_BIZ = 6; // Owned by a business
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
class NPCData {
|
||||
constructor(dbAssoc = false) {
|
||||
this.databaseId = 0;
|
||||
this.serverId = 0;
|
||||
this.name = "NPC";
|
||||
this.skin = 0;
|
||||
this.cash = 0;
|
||||
this.position = toVector3(0.0, 0.0, 0.0);
|
||||
this.rotation = toVector3(0.0, 0.0, 0.0);
|
||||
this.scale = toVector3(1.0, 1.0, 1.0);
|
||||
this.heading = 0.0;
|
||||
this.clan = 0;
|
||||
this.rank = 0;
|
||||
this.isWorking = false;
|
||||
this.jobUniform = this.skin;
|
||||
this.lastJobVehicle = null;
|
||||
this.job = 0;
|
||||
this.weapons = [];
|
||||
this.interior = 0;
|
||||
this.dimension = 0;
|
||||
this.walkStyle = 0;
|
||||
this.fightStyle = 0;
|
||||
this.health = 100;
|
||||
this.armour = 100;
|
||||
this.currentAction = AGRP_NPC_ACTION_NONE;
|
||||
this.triggers = [];
|
||||
this.typeFlags = 0;
|
||||
this.heedThreats = false;
|
||||
this.threats = 0;
|
||||
this.invincible = false;
|
||||
this.animationName = "";
|
||||
this.ownerType = AGRP_NPC_OWNER_NONE;
|
||||
this.ownerId = 0;
|
||||
this.enabled = false;
|
||||
|
||||
this.bodyParts = {
|
||||
hair: [0, 0],
|
||||
head: [0, 0],
|
||||
upper: [0, 0],
|
||||
lower: [0, 0],
|
||||
};
|
||||
|
||||
this.bodyProps = {
|
||||
hair: [0, 0],
|
||||
eyes: [0, 0],
|
||||
head: [0, 0],
|
||||
leftHand: [0, 0],
|
||||
rightHand: [0, 0],
|
||||
leftWrist: [0, 0],
|
||||
rightWrist: [0, 0],
|
||||
hip: [0, 0],
|
||||
leftFoot: [0, 0],
|
||||
rightFoot: [0, 0],
|
||||
};
|
||||
|
||||
this.triggers = [];
|
||||
|
||||
if (dbAssoc) {
|
||||
this.databaseId = toInteger(dbAssoc["npc_id"]);
|
||||
this.serverId = toInteger(dbAssoc["npc_server"]);
|
||||
this.name = dbAssoc["npc_name"];
|
||||
this.skin = toInteger(dbAssoc["npc_skin"]);
|
||||
this.cash = toInteger(dbAssoc["npc_cash"]);
|
||||
this.position = toVector3(toFloat(dbAssoc["npc_pos_x"]), toFloat(dbAssoc["npc_pos_y"]), toFloat(dbAssoc["npc_pos_z"]));
|
||||
this.rotation = toVector3(toFloat(dbAssoc["npc_rot_x"]), toFloat(dbAssoc["npc_rot_y"]), toFloat(dbAssoc["npc_rot_z"]));
|
||||
this.scale = toVector3(toFloat(dbAssoc["npc_scale_x"]), toFloat(dbAssoc["npc_scale_y"]), toFloat(dbAssoc["npc_scale_z"]));
|
||||
this.heading = toFloat(dbAssoc["npc_rot_z"]);
|
||||
this.rank = toInteger(dbAssoc["npc_rank"]);
|
||||
this.title = toInteger(dbAssoc["npc_title"]);
|
||||
this.job = toInteger(dbAssoc["npc_job"]);
|
||||
this.interior = toInteger(dbAssoc["npc_int"]);
|
||||
this.dimension = toInteger(dbAssoc["npc_vw"]);
|
||||
this.walkStyle = toInteger(dbAssoc["npc_walk_style"]);
|
||||
this.fightStyle = toInteger(dbAssoc["npc_fight_style"]);
|
||||
this.health = toInteger(dbAssoc["npc_health"]);
|
||||
this.armour = toInteger(dbAssoc["npc_armour"]);
|
||||
this.typeFlags = toInteger(dbAssoc["npc_type_flags"]);
|
||||
this.heedThreats = intToBool(dbAssoc["npc_headthreats"]);
|
||||
this.threats = toInteger(dbAssoc["npc_threats"]);
|
||||
this.invincible = intToBool(dbAssoc["npc_invincible"]);
|
||||
this.animationName = toString(dbAssoc["npc_animation"]);
|
||||
this.enabled = intToBool(dbAssoc["npc_enabled"]);
|
||||
this.lookAtPlayer = intToBool(dbAssoc["npc_lookatplr"]);
|
||||
|
||||
this.bodyParts = {
|
||||
hair: [toInteger(dbAssoc["npc_hd_part_hair_model"]) || 0, toInteger(dbAssoc["npc_hd_part_hair_texture"]) || 0],
|
||||
head: [toInteger(dbAssoc["npc_hd_part_head_model"]) || 0, toInteger(dbAssoc["npc_hd_part_head_texture"]) || 0],
|
||||
upper: [toInteger(dbAssoc["npc_hd_part_upper_model"]) || 0, toInteger(dbAssoc["npc_hd_part_upper_texture"]) || 0],
|
||||
lower: [toInteger(dbAssoc["npc_hd_part_lower_model"]) || 0, toInteger(dbAssoc["npc_hd_part_lower_texture"]) || 0],
|
||||
};
|
||||
|
||||
this.bodyProps = {
|
||||
hair: [toInteger(dbAssoc["npc_hd_prop_hair_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_hair_texture"]) || 0],
|
||||
eyes: [toInteger(dbAssoc["npc_hd_prop_eyes_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_eyes_texture"]) || 0],
|
||||
head: [toInteger(dbAssoc["npc_hd_prop_head_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_head_texture"]) || 0],
|
||||
leftHand: [toInteger(dbAssoc["npc_hd_prop_lefthand_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_lefthand_texture"]) || 0],
|
||||
rightHand: [toInteger(dbAssoc["npc_hd_prop_righthand_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_righthand_texture"]) || 0],
|
||||
leftWrist: [toInteger(dbAssoc["npc_hd_prop_leftwrist_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_leftwrist_texture"]) || 0],
|
||||
rightWrist: [toInteger(dbAssoc["npc_hd_prop_rightwrist_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_rightwrist_texture"]) || 0],
|
||||
hip: [toInteger(dbAssoc["npc_hd_prop_hip_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_hip_texture"]) || 0],
|
||||
leftFoot: [toInteger(dbAssoc["npc_hd_prop_leftfoot_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_leftfoot_texture"]) || 0],
|
||||
rightFoot: [toInteger(dbAssoc["npc_hd_prop_rightfoot_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_rightfoot_texture"]) || 0],
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
class NPCTriggerData {
|
||||
constructor(dbAssoc = false) {
|
||||
this.databaseId = 0;
|
||||
this.npcId = 0;
|
||||
this.index = 0;
|
||||
this.npc = 0;
|
||||
this.npcIndex = -1;
|
||||
this.triggerType = 0;
|
||||
this.conditions = [];
|
||||
this.responses = [];
|
||||
|
||||
if (dbAssoc) {
|
||||
this.databaseId = toInteger(dbAssoc["npc_trig_id"]);
|
||||
this.npc = toInteger(dbAssoc["npc_trig_npc"]);
|
||||
this.triggerType = toInteger(dbAssoc["npc_trig_type"]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
class NPCTriggerConditionData {
|
||||
constructor(dbAssoc = false) {
|
||||
this.databaseId = 0;
|
||||
this.triggerId = 0;
|
||||
this.index = 0;
|
||||
this.triggerIndex = 0;
|
||||
this.conditionType = 0;
|
||||
this.conditionValue = false;
|
||||
this.matchType = false;
|
||||
|
||||
if (dbAssoc) {
|
||||
this.databaseId = toInteger(dbAssoc["npc_trig_cond_id"]);
|
||||
this.npc = toInteger(dbAssoc["npc_trig_cond_trig"]);
|
||||
this.conditionType = toInteger(dbAssoc["npc_trig_cond_type"]);
|
||||
this.conditionValue = toInteger(dbAssoc["npc_trig_cond_val"]);
|
||||
this.matchType = toInteger(dbAssoc["npc_trig_cond_val"]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
class NPCTriggerResponseData {
|
||||
constructor(dbAssoc = false) {
|
||||
this.databaseId = 0;
|
||||
this.triggerId = 0;
|
||||
this.index = 0;
|
||||
this.triggerIndex = 0;
|
||||
this.responseType = 0;
|
||||
this.responseValue = false;
|
||||
|
||||
if (dbAssoc) {
|
||||
this.databaseId = toInteger(dbAssoc["npc_trig_resp_id"]);
|
||||
this.npc = toInteger(dbAssoc["npc_trig_resp_trig"]);
|
||||
this.responseType = toInteger(dbAssoc["npc_trig_resp_type"]);
|
||||
this.responseValue = toInteger(dbAssoc["npc_trig_resp_val"]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
function initNPCScript() {
|
||||
logToConsole(LOG_INFO, "[VRR.NPC]: Initializing NPC script ...");
|
||||
logToConsole(LOG_INFO, "[VRR.NPC]: NPC script initialized successfully!");
|
||||
logToConsole(LOG_DEBUG, "[AGRP.NPC]: Initializing NPC script ...");
|
||||
logToConsole(LOG_INFO, "[AGRP.NPC]: NPC script initialized successfully!");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
@@ -19,7 +217,7 @@ function initNPCScript() {
|
||||
* @return {NPCData} The NPC's data (class instancee)
|
||||
*/
|
||||
function getNPCData(npcId) {
|
||||
if(typeof getServerData().npcs[npcId] != "undefined") {
|
||||
if (typeof getServerData().npcs[npcId] != "undefined") {
|
||||
return getServerData().npcs[npcId];
|
||||
}
|
||||
return false;
|
||||
@@ -28,14 +226,14 @@ function getNPCData(npcId) {
|
||||
// ===========================================================================
|
||||
|
||||
function createNPCCommand(command, params, client) {
|
||||
if(areParamsEmpty(params)) {
|
||||
if (areParamsEmpty(params)) {
|
||||
messagePlayerSyntax(client, getCommandSyntaxText(command));
|
||||
return false;
|
||||
}
|
||||
|
||||
let skinIndex = getSkinModelIndexFromParams(params);
|
||||
|
||||
if(!skinIndex) {
|
||||
if (!skinIndex) {
|
||||
messagePlayerError(client, getLocaleString(client, "InvalidSkin"));
|
||||
return false;
|
||||
}
|
||||
@@ -48,15 +246,16 @@ function createNPCCommand(command, params, client) {
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
function loadNPCsFromDatabase() {
|
||||
logToConsole(LOG_INFO, `[VRR.NPC]: Loading NPCs from database ...`);
|
||||
async function loadNPCsFromDatabase() {
|
||||
logToConsole(LOG_DEBUG, `[AGRP.NPC]: Loading NPCs from database ...`);
|
||||
let dbConnection = connectToDatabase();
|
||||
let tempNPCs = [];
|
||||
let dbAssoc;
|
||||
if(dbConnection) {
|
||||
|
||||
if (dbConnection) {
|
||||
let dbQueryString = `SELECT * FROM npc_main WHERE npc_server = ${getServerId()} AND npc_enabled = 1`;
|
||||
dbAssoc = await fetchQueryAssoc(dbConnection, dbQueryString);
|
||||
for(let i in dbAssoc) {
|
||||
for (let i in dbAssoc) {
|
||||
let tempNPCData = new NPCData(dbAssoc[i]);
|
||||
tempNPCData.triggers = loadNPCTriggersFromDatabase();
|
||||
tempNPCs.push(tempNPCData);
|
||||
@@ -64,21 +263,22 @@ function loadNPCsFromDatabase() {
|
||||
disconnectFromDatabase(dbConnection);
|
||||
}
|
||||
|
||||
logToConsole(LOG_INFO, `[VRR.NPC]: ${tempNPCs.length} NPCs loaded from database successfully!`);
|
||||
logToConsole(LOG_DEBUG, `[AGRP.NPC]: ${tempNPCs.length} NPCs loaded from database successfully!`);
|
||||
return tempNPCs;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
function loadNPCTriggersFromDatabase(npcDatabaseId) {
|
||||
logToConsole(LOG_INFO, `[VRR.NPC]: Loading NPC triggers for NPC ${npcDatabaseId} from database ...`);
|
||||
async function loadNPCTriggersFromDatabase(npcDatabaseId) {
|
||||
logToConsole(LOG_DEBUG, `[AGRP.NPC]: Loading NPC triggers for NPC ${npcDatabaseId} from database ...`);
|
||||
let dbConnection = connectToDatabase();
|
||||
let tempNPCTriggers = [];
|
||||
let dbAssoc;
|
||||
if(dbConnection) {
|
||||
|
||||
if (dbConnection) {
|
||||
let dbQueryString = `SELECT * FROM npc_trig WHERE npc_trig_npc = ${npcDatabaseId} AND npc_trig_enabled = 1`;
|
||||
dbAssoc = await fetchQueryAssoc(dbConnection, dbQueryString);
|
||||
for(let i in dbAssoc) {
|
||||
for (let i in dbAssoc) {
|
||||
let tempNPCTriggerData = new NPCTriggerData(dbAssoc[i]);
|
||||
tempNPCTriggerData.conditions = loadNPCTriggerConditionsFromDatabase(tempNPCTriggerData.databaseId);
|
||||
tempNPCTriggerData.responses = loadNPCTriggerResponsesFromDatabase(tempNPCTriggerData.databaseId);
|
||||
@@ -87,60 +287,62 @@ function loadNPCTriggersFromDatabase(npcDatabaseId) {
|
||||
disconnectFromDatabase(dbConnection);
|
||||
}
|
||||
|
||||
logToConsole(LOG_INFO, `[VRR.NPC]: ${tempNPCTriggers.length} NPC triggers loaded for NPC ${npcDatabaseId} from database successfully!`);
|
||||
logToConsole(LOG_DEBUG, `[AGRP.NPC]: ${tempNPCTriggers.length} NPC triggers loaded for NPC ${npcDatabaseId} from database successfully!`);
|
||||
return tempNPCTriggers;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
function loadNPCTriggerConditionsFromDatabase(npcTriggerDatabaseId) {
|
||||
logToConsole(LOG_INFO, `[VRR.NPC]: Loading NPC trigger conditions for trigger ${npcTriggerDatabaseId} from database ...`);
|
||||
async function loadNPCTriggerConditionsFromDatabase(npcTriggerDatabaseId) {
|
||||
logToConsole(LOG_DEBUG, `[AGRP.NPC]: Loading NPC trigger conditions for trigger ${npcTriggerDatabaseId} from database ...`);
|
||||
let dbConnection = connectToDatabase();
|
||||
let tempNPCTriggerConditions = [];
|
||||
let dbAssoc;
|
||||
if(dbConnection) {
|
||||
|
||||
if (dbConnection) {
|
||||
let dbQueryString = `SELECT * FROM npc_cond WHERE npc_cond_trig = ${npcTriggerDatabaseId} AND npc_cond_enabled = 1`;
|
||||
dbAssoc = await fetchQueryAssoc(dbConnection, dbQueryString);
|
||||
for(let i in dbAssoc) {
|
||||
for (let i in dbAssoc) {
|
||||
let tempNPCTriggerConditionData = new NPCTriggerConditionData(dbAssoc[i]);
|
||||
tempNPCTriggerConditions.push(tempNPCTriggerConditionData);
|
||||
}
|
||||
disconnectFromDatabase(dbConnection);
|
||||
}
|
||||
|
||||
logToConsole(LOG_INFO, `[VRR.NPC]: ${tempNPCTriggerConditions.length} conditions loaded for trigger ${npcTriggerDatabaseId} from database successfully!`);
|
||||
logToConsole(LOG_DEBUG, `[AGRP.NPC]: ${tempNPCTriggerConditions.length} conditions loaded for trigger ${npcTriggerDatabaseId} from database successfully!`);
|
||||
return tempNPCTriggerConditions;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
function loadNPCTriggerResponsesFromDatabase(npcTriggerDatabaseId) {
|
||||
logToConsole(LOG_INFO, `[VRR.NPC]: Loading NPC trigger responses for trigger ${npcTriggerDatabaseId} from database ...`);
|
||||
async function loadNPCTriggerResponsesFromDatabase(npcTriggerDatabaseId) {
|
||||
logToConsole(LOG_DEBUG, `[AGRP.NPC]: Loading NPC trigger responses for trigger ${npcTriggerDatabaseId} from database ...`);
|
||||
let dbConnection = connectToDatabase();
|
||||
let tempNPCTriggerResponses = [];
|
||||
let dbAssoc;
|
||||
if(dbConnection) {
|
||||
|
||||
if (dbConnection) {
|
||||
let dbQueryString = `SELECT * FROM npc_resp WHERE npc_resp_trig = ${npcTriggerDatabaseId} AND npc_resp_enabled = 1`;
|
||||
dbAssoc = await fetchQueryAssoc(dbConnection, dbQueryString);
|
||||
for(let i in dbAssoc) {
|
||||
for (let i in dbAssoc) {
|
||||
let tempNPCTriggerResponseData = new NPCTriggerResponseData(dbAssoc[i]);
|
||||
tempNPCTriggerResponses.push(tempNPCTriggerResponseData);
|
||||
}
|
||||
disconnectFromDatabase(dbConnection);
|
||||
}
|
||||
|
||||
logToConsole(LOG_INFO, `[VRR.NPC]: ${tempNPCTriggerResponses.length} responses loaded for trigger ${npcTriggerDatabaseId} from database successfully!`);
|
||||
logToConsole(LOG_DEBUG, `[AGRP.NPC]: ${tempNPCTriggerResponses.length} responses loaded for trigger ${npcTriggerDatabaseId} from database successfully!`);
|
||||
return tempNPCTriggerResponses;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
function saveAllNPCsToDatabase() {
|
||||
if(getServerConfig().devServer) {
|
||||
if (getServerConfig().devServer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(let i in getServerData().npcs) {
|
||||
for (let i in getServerData().npcs) {
|
||||
saveNPCToDatabase(i);
|
||||
}
|
||||
}
|
||||
@@ -148,34 +350,34 @@ function saveAllNPCsToDatabase() {
|
||||
// ===========================================================================
|
||||
|
||||
function saveNPCToDatabase(npcDataId) {
|
||||
if(getServerConfig().devServer) {
|
||||
logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} can't be saved because server is running as developer only. Aborting save ...`);
|
||||
if (getServerConfig().devServer) {
|
||||
logToConsole(LOG_VERBOSE, `[AGRP.NPC]: NPC ${npcDataId} can't be saved because server is running as developer only. Aborting save ...`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(getNPCData(npcDataId) == false) {
|
||||
logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} data is invalid. Aborting save ...`);
|
||||
if (getNPCData(npcDataId) == false) {
|
||||
logToConsole(LOG_VERBOSE, `[AGRP.NPC]: NPC ${npcDataId} data is invalid. Aborting save ...`);
|
||||
return false;
|
||||
}
|
||||
|
||||
let tempNPCData = getNPCData(npcDataId);
|
||||
|
||||
if(tempNPCData.databaseId == -1) {
|
||||
logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} is a temp NPC. Aborting save ...`);
|
||||
if (tempNPCData.databaseId == -1) {
|
||||
logToConsole(LOG_VERBOSE, `[AGRP.NPC]: NPC ${npcDataId} is a temp NPC. Aborting save ...`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!tempNPCData.needsSaved) {
|
||||
logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} hasn't changed data. Aborting save ...`);
|
||||
if (!tempNPCData.needsSaved) {
|
||||
logToConsole(LOG_VERBOSE, `[AGRP.NPC]: NPC ${npcDataId} hasn't changed data. Aborting save ...`);
|
||||
return false;
|
||||
}
|
||||
|
||||
logToConsole(LOG_VERBOSE, `[VRR.NPC]: Saving NPC ${tempNPCData.databaseId} to database ...`);
|
||||
logToConsole(LOG_VERBOSE, `[AGRP.NPC]: Saving NPC ${tempNPCData.databaseId} to database ...`);
|
||||
let dbConnection = connectToDatabase();
|
||||
if(dbConnection) {
|
||||
if(tempNPCData.ped != false) {
|
||||
if(!tempNPCData.spawnLocked) {
|
||||
if(areServerElementsSupported()) {
|
||||
if (dbConnection) {
|
||||
if (tempNPCData.ped != false) {
|
||||
if (!tempNPCData.spawnLocked) {
|
||||
if (areServerElementsSupported()) {
|
||||
tempNPCData.position = tempNPCData.ped.position;
|
||||
tempNPCData.heading = tempNPCData.ped.heading;
|
||||
} else {
|
||||
@@ -187,6 +389,7 @@ function saveNPCToDatabase(npcDataId) {
|
||||
|
||||
let safeAnimationName = escapeDatabaseString(dbConnection, tempNPCData.animationName);
|
||||
let safeName = escapeDatabaseString(dbConnection, tempNPCData.name);
|
||||
let safeTitle = escapeDatabaseString(dbConnection, tempNPCData.title);
|
||||
|
||||
let data = [
|
||||
["npc_server", getServerId()],
|
||||
@@ -209,10 +412,19 @@ function saveNPCToDatabase(npcDataId) {
|
||||
["npc_threats", toInteger(tempNPCData.threats)],
|
||||
["npc_stay", boolToInt(tempNPCData.stay)],
|
||||
["npc_type_flags", toInteger(tempNPCData.typeFlags)],
|
||||
["npc_int", toInteger(tempNPCData.interior)],
|
||||
["npc_vw", toInteger(tempNPCData.dimension)],
|
||||
["npc_fight_style", toInteger(tempNPCData.fightStyle)],
|
||||
["npc_walk_style", toInteger(tempNPCData.walkStyle)],
|
||||
["npc_rank", toInteger(tempNPCData.rank)],
|
||||
["npc_title", toString(safeTitle)],
|
||||
["npc_enabled", boolToInt(tempNPCData.enabled)],
|
||||
["npc_lookatplr", boolToInt(tempNPCData.lookAtPlayer)],
|
||||
//["npc_recreate", toInteger(tempNPCData.recreateOnDeath)],
|
||||
];
|
||||
|
||||
let dbQuery = null;
|
||||
if(tempNPCData.databaseId == 0) {
|
||||
if (tempNPCData.databaseId == 0) {
|
||||
let queryString = createDatabaseInsertQuery("npc_main", data);
|
||||
dbQuery = queryDatabase(dbConnection, queryString);
|
||||
tempNPCData.databaseId = getDatabaseInsertId(dbConnection);
|
||||
@@ -227,7 +439,7 @@ function saveNPCToDatabase(npcDataId) {
|
||||
disconnectFromDatabase(dbConnection);
|
||||
return true;
|
||||
}
|
||||
logToConsole(LOG_VERBOSE, `[VRR.NPC]: Saved NPC ${npcDataId} to database!`);
|
||||
logToConsole(LOG_VERBOSE, `[AGRP.NPC]: Saved NPC ${npcDataId} to database!`);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -235,19 +447,19 @@ function saveNPCToDatabase(npcDataId) {
|
||||
// ===========================================================================
|
||||
|
||||
function setNPCDataIndexes() {
|
||||
for(let i in getServerData().npcs) {
|
||||
for (let i in getServerData().npcs) {
|
||||
getServerData().npcs[i].index = i;
|
||||
|
||||
for(let j in getServerData().npcs[i].triggers) {
|
||||
for (let j in getServerData().npcs[i].triggers) {
|
||||
getServerData().npcs[i].triggers[j].index = j;
|
||||
getServerData().npcs[i].triggers[j].npcIndex = i;
|
||||
|
||||
for(let k in getServerData().npcs[i].triggers[j].conditions) {
|
||||
for (let k in getServerData().npcs[i].triggers[j].conditions) {
|
||||
getServerData().npcs[i].triggers[j].conditions[k].index = k;
|
||||
getServerData().npcs[i].triggers[j].conditions[m].triggerIndex = j;
|
||||
}
|
||||
|
||||
for(let m in getServerData().npcs[i].triggers[j].responses) {
|
||||
for (let m in getServerData().npcs[i].triggers[j].responses) {
|
||||
getServerData().npcs[i].triggers[j].responses[m].index = m;
|
||||
getServerData().npcs[i].triggers[j].responses[m].triggerIndex = j;
|
||||
}
|
||||
@@ -260,13 +472,13 @@ function setNPCDataIndexes() {
|
||||
function spawnNPC(npcIndex) {
|
||||
let npcData = getNPCData(npcIndex);
|
||||
let ped = createGamePed(npcData.skin, npcData.position, npcData.rotation.z);
|
||||
if(ped) {
|
||||
if (ped) {
|
||||
getNPCData(npcIndex).ped = ped;
|
||||
setEntityData(ped, "vrr.dataIndex", npcIndex, false);
|
||||
if(npcData.animationName != "") {
|
||||
setEntityData(ped, "agrp.dataIndex", npcIndex, false);
|
||||
if (npcData.animationName != "") {
|
||||
let animationId = getAnimationFromParams(npcData.animationName);
|
||||
if(animationId != false) {
|
||||
setEntityData(ped, "vrr.anim", animationId, true);
|
||||
if (animationId != false) {
|
||||
setEntityData(ped, "agrp.anim", animationId, true);
|
||||
}
|
||||
}
|
||||
setElementDimension(ped, npcData.dimension);
|
||||
@@ -277,7 +489,7 @@ function spawnNPC(npcIndex) {
|
||||
// ===========================================================================
|
||||
|
||||
function spawnAllNPCs() {
|
||||
for(let i in getServerData().npcs) {
|
||||
for (let i in getServerData().npcs) {
|
||||
spawnNPC(i);
|
||||
}
|
||||
}
|
||||
@@ -285,9 +497,9 @@ function spawnAllNPCs() {
|
||||
// ===========================================================================
|
||||
|
||||
function deleteNPCCommand(command, params, client) {
|
||||
let closestNPC = getClosestNPC(getPlayerPosition(client));
|
||||
let closestNPC = getClosestNPC(getPlayerPosition(client), getPlayerDimension(client), getPlayerInterior(client));
|
||||
|
||||
if(!getNPCData(closestNPC)) {
|
||||
if (!getNPCData(closestNPC)) {
|
||||
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
|
||||
return false;
|
||||
}
|
||||
@@ -303,9 +515,9 @@ function deleteNPCCommand(command, params, client) {
|
||||
function deleteNPC(npcId) {
|
||||
quickDatabaseQuery(`DELETE FROM npc_main WHERE npc_id=${getNPCData(npcId).databaseId}`);
|
||||
|
||||
if(getNPCData(npcId)) {
|
||||
if(getNPCData(npcId).ped != false) {
|
||||
deleteEntity(getNPCData(npcId).ped);
|
||||
if (getNPCData(npcId)) {
|
||||
if (getNPCData(npcId).ped != false) {
|
||||
deleteGameElement(getNPCData(npcId).ped);
|
||||
}
|
||||
getServerData().npcs.splice(npcId, 1);
|
||||
}
|
||||
@@ -316,27 +528,27 @@ function deleteNPC(npcId) {
|
||||
// ===========================================================================
|
||||
|
||||
function setNPCAnimationCommand(command, params, client) {
|
||||
if(areParamsEmpty(params)) {
|
||||
if (areParamsEmpty(params)) {
|
||||
messagePlayerSyntax(client, getCommandSyntaxText(command));
|
||||
return false;
|
||||
}
|
||||
|
||||
let closestNPC = getClosestNPC(getPlayerPosition(client));
|
||||
let closestNPC = getClosestNPC(getPlayerPosition(client), getPlayerDimension(client), getPlayerInterior(client));
|
||||
let animationId = getAnimationFromParams(getParam(params, " ", 1));
|
||||
let animationPositionOffset = 1;
|
||||
|
||||
if(!getNPCData(closestNPC)) {
|
||||
if (!getNPCData(closestNPC)) {
|
||||
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!getAnimationData(animationId)) {
|
||||
if (!getAnimationData(animationId)) {
|
||||
messagePlayerError(client, getLocaleString(client, "InvalidAnimation"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(areThereEnoughParams(params, 2, " ")) {
|
||||
if(toInteger(animationPositionOffset) < 0 || toInteger(animationPositionOffset) > 3) {
|
||||
if (areThereEnoughParams(params, 2, " ")) {
|
||||
if (toInteger(animationPositionOffset) < 0 || toInteger(animationPositionOffset) > 3) {
|
||||
messagePlayerError(client, getLocaleString(client, "InvalidAnimationDistance"));
|
||||
return false;
|
||||
}
|
||||
@@ -353,15 +565,15 @@ function setNPCAnimationCommand(command, params, client) {
|
||||
// ===========================================================================
|
||||
|
||||
function setNPCNameCommand(command, params, client) {
|
||||
if(areParamsEmpty(params)) {
|
||||
if (areParamsEmpty(params)) {
|
||||
messagePlayerSyntax(client, getCommandSyntaxText(command));
|
||||
return false;
|
||||
}
|
||||
|
||||
let closestNPC = getClosestNPC(getPlayerPosition(client));
|
||||
let closestNPC = getClosestNPC(getPlayerPosition(client), getPlayerDimension(client), getPlayerInterior(client));
|
||||
let name = params;
|
||||
|
||||
if(!getNPCData(closestNPC)) {
|
||||
if (!getNPCData(closestNPC)) {
|
||||
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
|
||||
return false;
|
||||
}
|
||||
@@ -376,17 +588,75 @@ function setNPCNameCommand(command, params, client) {
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
function toggleNPCLookAtClosestPlayerCommand(command, params, client) {
|
||||
let closestNPC = getClosestNPC(getPlayerPosition(client));
|
||||
function setNPCClanCommand(command, params, client) {
|
||||
if (areParamsEmpty(params)) {
|
||||
messagePlayerSyntax(client, getCommandSyntaxText(command));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!getNPCData(closestNPC)) {
|
||||
let closestNPC = getClosestNPC(getPlayerPosition(client), getPlayerDimension(client), getPlayerInterior(client));
|
||||
let clanId = getClanFromParams(params);
|
||||
|
||||
if (!getNPCData(closestNPC)) {
|
||||
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!getClanData(clanId)) {
|
||||
messagePlayerError(client, getLocaleString(client, "InvalidClan"));
|
||||
return false;
|
||||
}
|
||||
|
||||
getNPCData(closestNPC).ownerType = AGRP_NPC_OWNER_CLAN;
|
||||
getNPCData(closestNPC).ownerId = getClanData(clanId).databaseId;
|
||||
getNPCData(closestNPC).needsSaved = true;
|
||||
|
||||
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} set {npcPink}${getNPCData(closestNPC).name}${MAINCOLOUR}'s clan to {clanOrange}${getClanData(clanId).name}`);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
function addNPCTriggerCommand(command, params, client) {
|
||||
if (areParamsEmpty(params)) {
|
||||
messagePlayerSyntax(client, getCommandSyntaxText(command));
|
||||
return false;
|
||||
}
|
||||
|
||||
let closestNPC = getClosestNPC(getPlayerPosition(client), getPlayerDimension(client), getPlayerInterior(client));
|
||||
let clanId = getClanFromParams(params);
|
||||
|
||||
if (!getNPCData(closestNPC)) {
|
||||
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!getClanData(clanId)) {
|
||||
messagePlayerError(client, getLocaleString(client, "InvalidClan"));
|
||||
return false;
|
||||
}
|
||||
|
||||
//let triggerData = new TriggerData();
|
||||
|
||||
getNPCData(closestNPC).ownerType = AGRP_NPC_OWNER_CLAN;
|
||||
getNPCData(closestNPC).ownerId = getClanData(clanId).databaseId;
|
||||
getNPCData(closestNPC).needsSaved = true;
|
||||
|
||||
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} set {npcPink}${getNPCData(closestNPC).name}${MAINCOLOUR}'s clan to {clanOrange}${getClanData(clanId).name}`);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
function toggleNPCLookAtClosestPlayerCommand(command, params, client) {
|
||||
let closestNPC = getClosestNPC(getPlayerPosition(client), getPlayerDimension(client), getPlayerInterior(client));
|
||||
|
||||
if (!getNPCData(closestNPC)) {
|
||||
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
|
||||
return false;
|
||||
}
|
||||
|
||||
getNPCData(closestNPC).lookAtClosestPlayer = !getNPCData(closestNPC).lookAtClosestPlayer;
|
||||
getNPCData(closestNPC).needsSaved = true;
|
||||
setEntityData(getNPCData(closestNPC).ped, "vrr.lookAtClosestPlayer", getNPCData(closestNPC).lookAtClosestPlayer, true);
|
||||
setEntityData(getNPCData(closestNPC).ped, "agrp.lookAtClosestPlayer", getNPCData(closestNPC).lookAtClosestPlayer, true);
|
||||
forcePlayerToSyncElementProperties(null, getNPCData(closestNPC).ped);
|
||||
//messagePlayerSuccess(client, getLocaleString(client, "NPCLookAtClosestPlayerSet", `{ALTCOLOUR}${getNPCData(closestNPC).name}{MAINCOLOUR}));
|
||||
}
|
||||
@@ -394,14 +664,14 @@ function toggleNPCLookAtClosestPlayerCommand(command, params, client) {
|
||||
// ===========================================================================
|
||||
|
||||
function getNPCInfoCommand(command, params, client) {
|
||||
if(areParamsEmpty(params)) {
|
||||
if (areParamsEmpty(params)) {
|
||||
messagePlayerSyntax(client, getCommandSyntaxText(command));
|
||||
return false;
|
||||
}
|
||||
|
||||
let closestNPC = getClosestNPC(getPlayerPosition(client));
|
||||
let closestNPC = getClosestNPC(getPlayerPosition(client), getPlayerDimension(client), getPlayerInterior(client));
|
||||
|
||||
if(!getNPCData(closestNPC)) {
|
||||
if (!getNPCData(closestNPC)) {
|
||||
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
|
||||
return false;
|
||||
}
|
||||
@@ -410,29 +680,29 @@ function getNPCInfoCommand(command, params, client) {
|
||||
|
||||
let ownerName = "Nobody";
|
||||
let ownerType = "None";
|
||||
switch(npcData.ownerType) {
|
||||
case VRR_NPCOWNER_CLAN:
|
||||
ownerName = getClanData(getClanIdFromDatabaseId(npcData.ownerId)).name;
|
||||
switch (npcData.ownerType) {
|
||||
case AGRP_NPC_OWNER_CLAN:
|
||||
ownerName = getClanData(getClanIndexFromDatabaseId(npcData.ownerId)).name;
|
||||
ownerType = "clan";
|
||||
break;
|
||||
|
||||
case VRR_NPCOWNER_JOB:
|
||||
ownerName = getJobData(getJobIdFromDatabaseId(npcData.ownerId)).name;
|
||||
case AGRP_NPC_OWNER_JOB:
|
||||
ownerName = getJobData(getJobIndexFromDatabaseId(npcData.ownerId)).name;
|
||||
ownerType = "job";
|
||||
break;
|
||||
|
||||
case VRR_NPCOWNER_PLAYER:
|
||||
case AGRP_NPC_OWNER_PLAYER:
|
||||
let subAccountData = loadSubAccountFromId(npcData.ownerId);
|
||||
ownerName = `${subAccountData.firstName} ${subAccountData.lastName} [${subAccountData.databaseId}]`;
|
||||
ownerType = "player";
|
||||
break;
|
||||
|
||||
case VRR_NPCOWNER_BIZ:
|
||||
case AGRP_NPC_OWNER_BIZ:
|
||||
ownerName = getBusinessData(getBusinessIdFromDatabaseId(npcData.ownerId)).name;
|
||||
ownerType = "business";
|
||||
break;
|
||||
|
||||
case VRR_NPCOWNER_PUBLIC:
|
||||
case AGRP_NPC_OWNER_PUBLIC:
|
||||
ownerName = "Nobody";
|
||||
ownerType = "public";
|
||||
break;
|
||||
@@ -452,23 +722,22 @@ function getNPCInfoCommand(command, params, client) {
|
||||
|
||||
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderNPCInfo")));
|
||||
let chunkedList = splitArrayIntoChunks(stats, 6);
|
||||
for(let i in chunkedList) {
|
||||
for (let i in chunkedList) {
|
||||
messagePlayerInfo(client, chunkedList[i].join(", "));
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
function getClosestNPC(position) {
|
||||
function getClosestNPC(position, dimension, interior) {
|
||||
let npcs = getServerData().npcs;
|
||||
|
||||
let interior = getPlayerInterior(client);
|
||||
let dimension = getPlayerDimension(client);
|
||||
|
||||
let closest = 0;
|
||||
for(let i in npcs) {
|
||||
if(getDistance(npcs[i].ped.position, position) < getDistance(npcs[closest].ped.position, position) && npcs[closest].interior == interior && npcs[closest].dimension == dimension) {
|
||||
closest = i;
|
||||
for (let i in npcs) {
|
||||
if (npcs[i].interior == interior && npcs[i].dimension == dimension) {
|
||||
if (getDistance(npcs[i].ped.position, position) < getDistance(npcs[closest].ped.position, position)) {
|
||||
closest = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,9 +759,9 @@ function createNPC(skinIndex, position, heading, interior, dimension) {
|
||||
let npcIndex = getServerData().npcs.push(tempNPCData);
|
||||
setNPCDataIndexes();
|
||||
|
||||
spawnNPC(npcIndex-1);
|
||||
spawnNPC(npcIndex - 1);
|
||||
|
||||
return npcIndex-1;
|
||||
return npcIndex - 1;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
Reference in New Issue
Block a user