Last active
October 19, 2024 21:42
-
-
Save Geritz/978cdd2ade053b5c357318306909c588 to your computer and use it in GitHub Desktop.
LCP Json parser for Roll20
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// LCP PC BUILDER by Spencer Moran | |
// AUTHORS NOTE: This script relies on a separate variables file called | |
// "ScriptData.js" which contains the datasets used by this script. | |
// YOU NEED BOTH FILES FOR THIS SCRIPT TO WORK. Due to load order restrictions | |
// The dataset will not register in this script until after you have first | |
// saved the script in Roll20. And then subsequently saved this script: | |
// STEP 1: Save ScriptData.js | |
// STEP 2: Save lcp_pc_builder.js | |
// You will need to do this each time you make a change to the datasets. | |
// CHAT TABLE FACTORY | |
var CTF = { | |
'addTemplate' : function(template="default"){ | |
return "&{template:"+template+"}"; | |
}, | |
'addTableHeader' : function(name){ | |
return "{{name="+name+"}}"; | |
}, | |
'addTableItem' : function(content){ | |
return "{{"+content+"}}"; | |
}, | |
'addTableButton' : function(content,link="!lncr_stub"){ | |
return "["+content+"]("+link+")"; | |
} | |
} | |
// FUNCTIONS | |
// HELPER FUNCTIONS | |
function p_lncr_roll20objcontains(value,type='macro'){ | |
try { | |
let test = findObjs({ | |
_type: type, | |
name: value | |
}); | |
return ((test.length <= 0)? false : true); | |
} catch (e){ | |
sendChat("LANCER CORE HELPER", "Something went wrong when attempting to do a contains test:" + e); | |
} | |
} | |
// FIND LCP ENTRY BY NAME | |
function FindPcFrameByName(frameName){ | |
let frame; | |
frame_data_set.forEach((element) => { | |
if (typeof frame != 'undefined'){ | |
return frame; | |
} | |
frame = element.find((obj) => obj.name.toLowerCase() == frameName.toLowerCase()); | |
}); | |
if (typeof frame == 'undefined'){ | |
sendChat("LCP BUILD ERROR", "could not find a frame called \"" + frameName + "\" in stored LCP files"); | |
} | |
return frame; | |
} | |
function FindPcSystemByName(systemName){ | |
let system; | |
system_data_set.forEach((element) => { | |
if (typeof system != 'undefined'){ | |
return system; | |
} | |
system = element.find((obj) => obj.name.toLowerCase() == systemName.toLowerCase()); | |
}); | |
if (typeof system == 'undefined'){ | |
sendChat("LCP BUILD ERROR", "could not find a system called \"" + systemName + "\" in stored LCP files"); | |
} | |
return system; | |
} | |
function FindPcWeaponByName(weaponName){ | |
let weapon; | |
weapon_data_set.forEach((element) => { | |
if (typeof weapon != 'undefined'){ | |
return weapon; | |
} | |
weapon = element.find((obj) => obj.name.toLowerCase() == weaponName.toLowerCase()); | |
}); | |
if (typeof weapon == 'undefined'){ | |
sendChat("LCP BUILD ERROR", "could not find a weapon called \"" + weaponName + "\" in stored LCP files"); | |
} | |
return weapon; | |
} | |
function FindPcModByName(modName){ | |
let mod; | |
mod_data_set.forEach((element) => { | |
log(element); | |
if (typeof mod !== 'undefined'){ | |
return mod; | |
} | |
mod = element.find((obj) => obj.name.toLowerCase() == modName.toLowerCase()); | |
}); | |
if (typeof mod == 'undefined'){ | |
sendChat("LCP BUILD ERROR", "could not find a mod called \"" + modName + "\" in stored LCP files"); | |
} | |
return mod; | |
} | |
function FindPcTalentByName(talentName){ | |
let talent; | |
talent_data_set.forEach((element) => { | |
if (typeof talent != 'undefined'){ | |
return talent; | |
} | |
talent = element.find((obj) => obj.name.toLowerCase() == talentName.toLowerCase()); | |
}); | |
if (typeof talent == 'undefined'){ | |
sendChat("LCP BUILD ERROR", "could not find a talent called \"" + talentName + "\" in stored LCP files"); | |
} | |
return talent; | |
} | |
function FindPcCoreBonusByName(cbName){ | |
let cb; | |
core_bonus_data_set.forEach((element) => { | |
if (typeof cb != 'undefined'){ | |
return cb; | |
} | |
cb = element.find((obj) => obj.name.toLowerCase() == cbName.toLowerCase()); | |
}); | |
if (typeof cb == 'undefined'){ | |
sendChat("LCP BUILD ERROR", "could not find a core bonus called \"" + cbName + "\" in stored LCP files"); | |
} | |
return cb; | |
} | |
// FIND LCP ENTRY BY ID | |
function FindPcFrameById(frameId){ | |
let frame; | |
frame_data_set.forEach((element) => { | |
if (typeof frame != 'undefined'){ | |
return frame; | |
} | |
frame = element.find((obj) => obj.id.toLowerCase() == frameId.toLowerCase()); | |
}); | |
if (typeof frame == 'undefined'){ | |
sendChat("LCP BUILD ERROR", "could not find a frame called \"" + frameId + "\" in stored LCP files"); | |
} | |
return frame; | |
} | |
function FindPcSystemById(systemId){ | |
let system; | |
system_data_set.forEach((element) => { | |
if (typeof system != 'undefined'){ | |
return system; | |
} | |
system = element.find((obj) => obj.id.toLowerCase() == systemId.toLowerCase()); | |
}); | |
if (typeof system == 'undefined'){ | |
sendChat("LCP BUILD ERROR", "could not find a system called \"" + systemId + "\" in stored LCP files"); | |
} | |
return system; | |
} | |
function FindPcWeaponById(weaponId){ | |
let weapon; | |
weapon_data_set.forEach((element) => { | |
if (typeof weapon != 'undefined'){ | |
return weapon; | |
} | |
weapon = element.find((obj) => obj.id.toLowerCase() == weaponId.toLowerCase()); | |
}); | |
if (typeof weapon == 'undefined'){ | |
sendChat("LCP BUILD ERROR", "could not find a weapon called \"" + weaponId + "\" in stored LCP files"); | |
} | |
return weapon; | |
} | |
function FindPcModById(modId){ | |
let mod; | |
mod_data_set.forEach((element) => { | |
if (typeof mod != 'undefined'){ | |
return mod; | |
} | |
mod = element.find((obj) => obj.id.toLowerCase() == modId.toLowerCase()); | |
}); | |
if (typeof mod == 'undefined'){ | |
sendChat("LCP BUILD ERROR", "could not find a mod called \"" + modId + "\" in stored LCP files"); | |
} | |
return mod; | |
} | |
function FindPcTalentById(talentId){ | |
let talent; | |
talent_data_set.forEach((element) => { | |
if (typeof talent != 'undefined'){ | |
return talent; | |
} | |
talent = element.find((obj) => obj.id.toLowerCase() == talentId.toLowerCase()); | |
}); | |
if (typeof talent == 'undefined'){ | |
sendChat("LCP BUILD ERROR", "could not find a talent called \"" + talentId + "\" in stored LCP files"); | |
} | |
return talent; | |
} | |
function FindPcCoreBonusById(cbId){ | |
let cb; | |
core_bonus_data_set.forEach((element) => { | |
if (typeof cb != 'undefined'){ | |
return cb; | |
} | |
cb = element.find((obj) => obj.id.toLowerCase() == cbId.toLowerCase()); | |
}); | |
if (typeof cb == 'undefined'){ | |
sendChat("LCP BUILD ERROR", "could not find a core bonus called \"" + cbId + "\" in stored LCP files"); | |
} | |
return cb; | |
} | |
function FindSystemTagById(tagId){ | |
let tag; | |
tag_data_set.forEach((element) => { | |
if (typeof tag != 'undefined'){ | |
return tag; | |
} | |
tag = element.find((obj) => obj.id.toLowerCase() == tagId.toLowerCase()); | |
}); | |
if (typeof tag == 'undefined'){ | |
sendChat("LCP BUILD ERROR", "could not find a tag called \"" + tagId + "\" in stored LCP files"); | |
} | |
return tag; | |
} | |
// FIND NPC THINGS | |
function FindNpcClass(className){ | |
let npcClass; | |
npcClassDataSet.forEach((element) => { | |
let classTarget = element.find((npc) => npc.name.toLowerCase() == className.toLowerCase()); // Retrieve the class element by name; | |
if (typeof classTarget !== 'undefined'){ | |
npcClass = classTarget; | |
} | |
}); | |
return npcClass; | |
} | |
function FindNpcFeature(id){ | |
let desiredFeature; | |
npcFeatureDataSet.forEach((element) => { | |
let featureTarget = element.find((feature) => feature.id.toLowerCase() == id.toLowerCase()); | |
if (typeof featureTarget !== 'undefined'){ | |
desiredFeature=featureTarget; | |
} | |
}); | |
return desiredFeature; | |
} | |
function FindNpcTemplate(templateName){ | |
let npcTemplate; | |
npcTemplateDataSet.forEach((element) => { | |
let templateTarget = element.find((feature) => feature.name.toLowerCase() == templateName.toLowerCase()); | |
if (typeof templateTarget !== 'undefined'){ | |
npcTemplate=templateTarget; | |
} | |
}); | |
return npcTemplate; | |
} | |
// FIND FROM ANY | |
function FindPcFeatureById(id, type){ | |
switch(type){ | |
case 'frame': | |
return FindPcFrameById(id); | |
case 'system': | |
return FindPcSystemById(id); | |
case 'weapon': | |
return FindPcWeaponById(id); | |
case 'mod': | |
return FindPcModById(id); | |
case 'talent': | |
return FindPcTalentById(id); | |
case 'corebonus': | |
return FindPcCoreBonusById(id); | |
case 'tag': | |
return FindSystemTagById(id); | |
default: | |
sendChat("ERROR", "Invalid type: " + type); | |
break; | |
} | |
} | |
// SYSTEM MENUS | |
function DisplayPcItemList(msg, type, displayOnly = false){ | |
let itemList = ""; | |
switch (type){ | |
case 'frame': | |
frame_data_set.forEach((element) => { | |
element.forEach((item) => { | |
if (item.name != "ERR: DATA NOT FOUND") { | |
itemList += CTF.addTableButton(item.name, "!lcp_builder_pc_add_macro " + item.id + " frame true"); | |
}; | |
}); | |
}); | |
break; | |
case 'weapon': | |
weapon_data_set.forEach((element) => { | |
element.forEach((item) => { | |
if (item.name != "ERR: DATA NOT FOUND") { | |
itemList += CTF.addTableButton(item.name, "!lcp_builder_pc_add_macro " + item.id + " weapon true"); | |
}; | |
}); | |
}); | |
break; | |
case 'system': | |
system_data_set.forEach((element) => { | |
element.forEach((item) => { | |
if (item.name != "ERR: DATA NOT FOUND") { | |
itemList += CTF.addTableButton(item.name, "!lcp_builder_pc_add_macro " + item.id + " system true"); | |
}; | |
}); | |
}); | |
break; | |
case 'corebonus': | |
core_bonus_data_set.forEach((element) => { | |
element.forEach((item) => { | |
if (item.name != "ERR: DATA NOT FOUND") { | |
itemList += CTF.addTableButton(item.name, "!lcp_builder_pc_add_macro " + item.id + " corebonus true"); | |
}; | |
}); | |
}); | |
break; | |
case 'mod': | |
mod_data_set.forEach((element) => { | |
element.forEach((item) => { | |
if (item.name != "ERR: DATA NOT FOUND") { | |
itemList += CTF.addTableButton(item.name, "!lcp_builder_pc_add_macro " + item.id + " mod true"); | |
}; | |
}); | |
}); | |
break; | |
case 'talent': | |
talent_data_set.forEach((element) => { | |
element.forEach((item) => { | |
if (item.name != "ERR: DATA NOT FOUND") { | |
itemList += CTF.addTableButton(item.name, "!lcp_builder_pc_add_macro " + item.id + " talent true"); | |
}; | |
}); | |
}); | |
break; | |
case 'tag': | |
tag_data_set.forEach((element) => { | |
element.forEach((item) => { | |
if (item.name != "ERR: DATA NOT FOUND") { | |
itemList += CTF.addTableButton(item.name, "!lcp_builder_pc_add_macro " + item.id + " tag true"); | |
}; | |
}); | |
}); | |
break; | |
default: | |
break; | |
} | |
let output = CTF.addTemplate() + CTF.addTableHeader(type.toUpperCase() +" LIST") + CTF.addTableItem(itemList); | |
sendChat("LCP BUILDER", "/w gm " + output); | |
} | |
// NPC MENUS | |
function DisplayTemplateList(msg, tier, displayOnly = false){ | |
let TemplateItems = ""; | |
npcTemplateDataSet.forEach((element) => { | |
element.forEach((npcTemplate) => { | |
TemplateItems += CTF.addTableButton(npcTemplate.name, "!lcp_builder_add_npc_template " + npcTemplate.name + " " + tier + " true"); | |
}); | |
}); | |
let output = CTF.addTemplate() + CTF.addTableHeader("Template List Tier " + tier) + CTF.addTableItem(TemplateItems); | |
sendChat("LCP BUILDER", "/w gm " + output); | |
} | |
function DisplayClassList(msg, tier, displayOnly = false){ | |
let ArtilleryList = ""; | |
let BiologicalList = ""; | |
let ControllerList = ""; | |
let DefenderList = ""; | |
let StrikerList = ""; | |
let SupportList = ""; | |
let OtherList = ""; | |
npcClassDataSet.forEach((element) => { | |
element.forEach((npcClass) => { | |
if (npcClass.role == "artillery"){ | |
ArtilleryList += CTF.addTableButton(npcClass.name,"!lcp_builder_add_npc_class " + npcClass.name + " " + tier + " true"); | |
} | |
else if (npcClass.role == "biological"){ | |
BiologicalList += CTF.addTableButton(npcClass.name, "!lcp_builder_add_npc_class " + npcClass.name + " " + tier + " true"); | |
} | |
else if (npcClass.role == "controller"){ | |
ControllerList += CTF.addTableButton(npcClass.name,"!lcp_builder_add_npc_class " + npcClass.name + " " + tier + " true"); | |
} | |
else if (npcClass.role == "defender"){ | |
DefenderList += CTF.addTableButton(npcClass.name,"!lcp_builder_add_npc_class " + npcClass.name + " " + tier + " true"); | |
} | |
else if (npcClass.role == "striker"){ | |
StrikerList += CTF.addTableButton(npcClass.name,"!lcp_builder_add_npc_class " + npcClass.name + " " + tier + " true"); | |
} | |
else if (npcClass.role == "support"){ | |
SupportList += CTF.addTableButton(npcClass.name,"!lcp_builder_add_npc_class " + npcClass.name + " " + tier + " true"); | |
} | |
else { | |
OtherList += CTF.addTableButton(npcClass.name,"!lcp_builder_add_npc_class " + npcClass.name + " " + tier + " true"); | |
} | |
}); | |
}); | |
sendChat("LCP BUILDER", "/w gm " + CTF.addTemplate() | |
+ CTF.addTableHeader("Class List Tier " + tier) | |
+ CTF.addTableItem("Artillery =" + ArtilleryList) | |
+ CTF.addTableItem("Biological =" + BiologicalList) | |
+ CTF.addTableItem("Controller =" + ControllerList) | |
+ CTF.addTableItem("Defender =" + DefenderList) | |
+ CTF.addTableItem("Striker =" + StrikerList) | |
+ CTF.addTableItem("Support =" + SupportList) | |
+ CTF.addTableItem("Other =" + OtherList)); | |
} | |
function MenuNpcClassTier(msg){ | |
let output = CTF.addTemplate() | |
+ CTF.addTableHeader("Select NPC Tier") | |
+ CTF.addTableItem("Classes =" + CTF.addTableButton("Tier 1", "!lcp_builder_display_class_list 1") + CTF.addTableButton("Tier 2", "!lcp_builder_display_class_list 2") + CTF.addTableButton("Tier 3", "!lcp_builder_display_class_list 3")) | |
+ CTF.addTableItem("Templates =" + CTF.addTableButton("Tier 1", "!lcp_builder_display_template_list 1") + CTF.addTableButton("Tier 2", "!lcp_builder_display_template_list 2") + CTF.addTableButton("Tier 3", "!lcp_builder_display_template_list 3")); | |
sendChat("LCP BUILDER", "/w gm " + output); | |
} | |
// DISPLAY MENU FOR PC OPTIONS | |
function MenuPcOptionsList(msg){ | |
let output = CTF.addTemplate() | |
+ CTF.addTableHeader("PC Build Menu -- [IMPORT CHARACTER](!lncr_stub)") | |
+ CTF.addTableItem("Frames =" + CTF.addTableButton("FRAMES", "!lcp_builder_displaylist frame true")) | |
+ CTF.addTableItem("Weapons =" + CTF.addTableButton("WEAPONS", "!lcp_builder_displaylist weapon true")) | |
+ CTF.addTableItem("Systems = " + CTF.addTableButton("SYSTEMS", "!lcp_builder_displaylist system true")) | |
+ CTF.addTableItem("Core Bonuses = " + CTF.addTableButton("CORE BONUSES", "!lcp_builder_displaylist corebonus true")) | |
+ CTF.addTableItem("Mods = " + CTF.addTableButton("MODS", "!lcp_builder_displaylist mod true")) | |
+ CTF.addTableItem("Talents = " + CTF.addTableButton("TALENTS", "!lcp_builder_displaylist talent true")); | |
+ CTF.addTableItem("Tags = " + CTF.addTableButton("TAGS", "!lcp_builder_displaylist tags true")); | |
sendChat("LCP BUILDER", "/w gm " + output); | |
} | |
// MACRO && SHEET MANIPULATION | |
// ADD A FEATURE MACRO TO A CHARACTER SHEET | |
function AddPcFeature(msg, id, type, displayOnly = false){ | |
if (typeof msg.selected === 'undefined') { | |
sendChat("LANCER CORE HELPER", "&{template:default}{{name=NO TOKEN SELECTED}}{{You must select a token for this macro}}"); | |
return; | |
} | |
let obj = getObj(msg.selected[0]._type,msg.selected[0]._id); | |
let characterID = obj.get('represents'); | |
let tokobj = getObj('graphic', msg.selected[0]._id); | |
let tokenName = tokobj.get('name').toLowerCase(); | |
if (!displayOnly) { sendChat("LCP BUILDER", "Adding " + id + " to " + tokenName); } | |
let desiredFeature = FindPcFeatureById(id, type); | |
if (typeof desiredFeature === 'undefined'){ | |
sendChat("LCP BUILDER", "Feature Not Found in Data Set. ID: " + id); | |
return; | |
} | |
let fAction; | |
let fName; | |
let fId; | |
let fSource; | |
let fMounts; | |
let fStats; | |
let fTraits; | |
let core_system; | |
let subList; | |
let fTypesAllowed; | |
let fEffect; | |
let fActions; | |
let fTags; | |
switch(type){ | |
case 'frame': | |
fId = desiredFeature["id"]; | |
fSource = desiredFeature["source"]; | |
fName = desiredFeature["name"]; | |
fMounts = desiredFeature["mounts"]; | |
fStats = desiredFeature["stats"]; | |
fTraits = desiredFeature["traits"]; | |
core_system = desiredFeature["core_system"]; | |
subList = ""; | |
// MECH NAME | |
fAction = CTF.addTemplate() | |
+ CTF.addTableHeader(fSource + " " + fName + " " + CTF.addTableButton("Add To Sheet", "!lcp_builder_pc_add_macro " + fId + " " + type)); | |
// MECH MOUNTS | |
fMounts.forEach((mount) => { subList += CTF.addTableButton(mount, "!lncr_stub"); }); | |
fAction += CTF.addTableItem("Mounts = " + subList); | |
subList = ""; | |
// MECH STATS | |
fAction += CTF.addTableItem("Stats = " | |
+ CTF.addTableButton("SIZE " + fStats.size) | |
+ CTF.addTableButton("STRUCTURE " + fStats.structure) | |
+ CTF.addTableButton("CORE STRESS " + fStats.stress) | |
+ CTF.addTableButton("ARMOR " + fStats.armor) | |
+ CTF.addTableButton("HP " + fStats.hp) | |
+ CTF.addTableButton("EVASION " + fStats.evasion) | |
+ CTF.addTableButton("E-DEFENSE " + fStats.edef) | |
+ CTF.addTableButton("HEAT CAP " + fStats.heatcap) | |
+ CTF.addTableButton("REPAIRS " + fStats.repcap) | |
+ CTF.addTableButton("SENSORS " + fStats.sensor_range) | |
+ CTF.addTableButton("TECH ATTACK " + fStats.tech_attack) | |
+ CTF.addTableButton("SAVE " + fStats.save) | |
+ CTF.addTableButton("SPEED " + fStats.speed) | |
+ CTF.addTableButton("SP " + fStats.sp) | |
); | |
// MECH TRAITS | |
fAction += CTF.addTableItem("TRAITS"); | |
fTraits.forEach((trait) => { fAction += CTF.addTableItem(trait.name + " = " + trait['description'])}); | |
// MECH CORE SYSTEM | |
fAction += CTF.addTableItem("CORE SYSTEM = **" + core_system.name + "**"); | |
// MECH PASSIVE | |
if (typeof core_system['passive_name'] !== 'undefined'){ | |
fAction += CTF.addTableItem("PASSIVE = " + core_system.passive_name + " - " + core_system.passive_effect); | |
} | |
if (typeof core_system['passive_actions'] !== 'undefined') | |
{ | |
core_system.passive_actions.forEach((passive) => { | |
let passiveName = passive.name; | |
let passiveActivation = passive.activation; | |
let passiveFrequency = passive.frequency; | |
let passiveTrigger = passive.trigger; | |
let passiveDetail = passive.detail; | |
fAction += CTF.addTableItem("" | |
+ ((typeof passiveActivation !== 'undefined') ? CTF.addTableButton(passive.activation, "!lncr_stub") : "") | |
+ ((typeof passiveFrequency !== 'undefined') ? CTF.addTableButton(passiveFrequency, "!lncr_stub") : "") | |
+ " = " | |
+ ((typeof passiveName !== 'undefined') ? "**" + passiveName + "** - " : "") | |
+ ((typeof passiveTrigger !== 'undefined') ? "<br>**Trigger** - " + passiveTrigger : "") | |
+ ((typeof passiveDetail !== 'undefined') ? "<br><br>" + passiveDetail : "") | |
); | |
}) | |
} | |
// MECH ACTIVE | |
fAction += CTF.addTableItem( CTF.addTableButton(core_system.activation,"!lncr_stub") + " = " + "**" + core_system.active_name + "** - " + core_system.active_effect); | |
if (typeof core_system['active_actions'] !== 'undefined') | |
{ | |
core_system.active_actions.forEach((action) => { | |
let actionName = action.name; | |
let actionActivation = action.activation; | |
let actionFrequency = action.frequency; | |
let actionTrigger = action.trigger; | |
let actionDetail = action.detail; | |
fAction += CTF.addTableItem("" | |
+ ((typeof actionActivation !== 'undefined') ? CTF.addTableButton(action.activation, "!lncr_stub") : "") | |
+ ((typeof actionFrequency !== 'undefined') ? CTF.addTableButton(actionFrequency, "!lncr_stub") : "") | |
+ " = " | |
+ ((typeof actionName !== 'undefined') ? "**" + actionName + "** - " : "") | |
+ ((typeof actionTrigger !== 'undefined') ? "<br>**Trigger** - " + actionTrigger : "") | |
+ ((typeof actionDetail !== 'undefined') ? "<br><br>" + actionDetail : "") | |
); | |
}) | |
} | |
if (typeof core_system['deployables'] !== 'undefined'){ | |
fAction += CTF.addTableItem("DEPLOYABLES"); | |
core_system.deployables.forEach((deployable) => { | |
let deployName = deployable.name; | |
let deployType = deployable.type; | |
let deployDetail = deployable.detail; | |
let deployActivation = deployable.activation; | |
let deployRecall = deployable.recall; | |
let deployRedeploy = deployable.redeploy; | |
let deploySize = deployable.size; | |
let deployHp = deployable.hp; | |
fAction += CTF.addTableItem("" | |
+ ((typeof deployName !== 'undefined') ? "**" + deployName + "** <br> " : "") | |
+ ((typeof deployActivation !== 'undefined') ? CTF.addTableButton(deployActivation, "!lncr_stub") : "") | |
+ ((typeof deployRecall !== 'undefined') ? CTF.addTableButton("RECALL - " + deployRecall, "!lncr_stub") : "") | |
+ ((typeof deployRedeploy !== 'undefined') ? CTF.addTableButton("REDEPLOY - "+ deployRecall, "!lncr_stub") : "") | |
+ " = " | |
+ ((typeof deploySize !== 'undefined') ? " - **Size: " + deploySize + "** " : "") | |
+ ((typeof deployHp !== 'undefined') ? "**HP: " + deployHp + "**": "") | |
+ ((typeof deployDetail !== 'undefined') ? "<br>" + deployDetail : "") | |
); | |
}) | |
} | |
if (typeof core_system['integrated'] !== 'undefined'){ | |
fAction += CTF.addTableItem("INTEGRATED EQUIPMENT"); | |
core_system.integrated.forEach((equipment) => { | |
let integratedItem = FindPcFeatureById(equipment, 'weapon'); | |
fAction += CTF.addTableItem(integratedItem.name + " = " + CTF.addTableButton(integratedItem.name, "!lcp_builder_pc_add_macro " + equipment + " weapon")); | |
}) | |
} | |
break; | |
case 'mod': | |
fId = desiredFeature["id"]; | |
fName = desiredFeature["name"]; | |
fSource = desiredFeature["source"]; | |
fTypesAllowed = desiredFeature["allowed_types"]; | |
fEffect = desiredFeature["effect"]; | |
fActions = desiredFeature["actions"]; | |
fTags = desiredFeature["tags"]; | |
subList = ""; | |
fAction = CTF.addTemplate() | |
+ CTF.addTableHeader(fName + " " + CTF.addTableButton("Add To Sheet", "!lcp_builder_pc_add_macro " + fId + " " + type)) | |
+ CTF.addTableItem("Combatible Types = " + fTypesAllowed) | |
+ CTF.addTableItem("Effect = " + fEffect); | |
if (typeof fActions !== 'undefined'){ | |
fActions.forEach((action) =>{ | |
fAction += CTF.addTableItem(action.name + "<br>" + CTF.addTableButton(action.activation) + " = " + action.detail); | |
}) | |
} | |
if (typeof fTags !== 'undefined'){ | |
sublist = ""; | |
fTags.forEach((tag) => { | |
let tagInfo = FindPcFeatureById(tag.id,'tag'); | |
sublist += CTF.addTableButton(((tag.val !== 'undefined') ? tagInfo.name.replace("{VAL}", tag.val) : tagInfo.name), "!lcp_builder_pc_add_macro " + tag.id + " tag false"); | |
}) | |
fAction += CTF.addTableItem("Tags = " + sublist); | |
} | |
break; | |
case 'system': | |
fId = desiredFeature["id"]; | |
fName = desiredFeature["name"]; | |
fSource = desiredFeature["source"]; | |
fEffect = desiredFeature["effect"]; | |
fActions = desiredFeature["actions"]; | |
fTags = desiredFeature["tags"]; | |
subList = ""; | |
fAction = CTF.addTemplate() | |
+ CTF.addTableHeader(fName + " " + CTF.addTableButton("Add To Sheet", "!lcp_builder_pc_add_macro " + fId + " " + type)) | |
+ ((typeof fEffect !== 'undefined') ? CTF.addTableItem("Effect = " + fEffect) : ""); | |
if (typeof fActions !== 'undefined'){ | |
fActions.forEach((action) =>{ | |
fAction += CTF.addTableItem(((typeof action.name !== 'undefined') ? action.name + "<br>" : "") + CTF.addTableButton(action.activation) + " = " + action.detail); | |
}) | |
} | |
if (typeof fTags !== 'undefined'){ | |
sublist = ""; | |
fTags.forEach((tag) => { | |
let tagInfo = FindPcFeatureById(tag.id,'tag'); | |
sublist += CTF.addTableButton(((tag.val !== 'undefined') ? tagInfo.name.replace("{VAL}", tag.val) : tagInfo.name), "!lcp_builder_pc_add_macro " + tag.id + " tag false"); | |
}) | |
fAction += CTF.addTableItem("Tags = " + sublist); | |
} | |
break; | |
case 'weapon': | |
let wepid = desiredFeature['id']; | |
let wepdamage = desiredFeature['damage']; | |
let wepmount = desiredFeature['mount']; | |
let wepname = desiredFeature['name']; | |
fName = desiredFeature['name']; | |
let weprange = desiredFeature['range']; | |
let webdescription = desiredFeature['description']; | |
let weplicense = desiredFeature['license']; | |
let wepsource = desiredFeature['source']; | |
let weptags = desiredFeature['tags']; | |
let weptype = desiredFeature['type']; | |
let weponcrit = desiredFeature['on_crit']; | |
let wepeffect = desiredFeature['effect']; | |
let wepactions = desiredFeature['actions']; | |
let wepprofiles = desiredFeature['profiles']; | |
let weponhit = desiredFeature['on_hit']; | |
let weponattack = desiredFeature['on_attack']; | |
fAction = CTF.addTemplate() | |
+ CTF.addTableHeader(wepname + " " + CTF.addTableButton("Add To Sheet", "!lcp_builder_pc_add_macro " + wepid + " " + type)) | |
+ CTF.addTableItem("Type = **" + wepmount + " " + weptype + "**") | |
+ CTF.addTableItem("Attack Roll = [[1d20 + @{selected|grit}]] *ACC/DIFF** [[1d6]][[1d6]][[1d6]][[1d6]][[1d6]][[1d6]]"); | |
if (typeof wepdamage !== 'undefined'){ | |
sublist = ""; | |
wepdamage.forEach((damtype) => { | |
sublist += damtype.type + " [[" + damtype.val + "]]<br>"; | |
}) | |
fAction += CTF.addTableItem("Damage = " + sublist); | |
} | |
if (typeof weprange !== 'undefined'){ | |
sublist = ""; | |
weprange.forEach((range) => { | |
sublist += range.type + " " + range.val + "<br>"; | |
}) | |
fAction += CTF.addTableItem("Range = " + sublist); | |
} | |
if (typeof weponcrit !== 'undefined'){ | |
fAction += CTF.addTableItem("On Crit = " + weponcrit); | |
} | |
if (typeof weponhit !== 'undefined'){ | |
fAction += CTF.addTableItem("On Hit = " + weponhit); | |
} | |
if (typeof weponattack !== 'undefined'){ | |
fAction += CTF.addTableItem("On Attack = " + weponattack); | |
} | |
if (typeof wepeffect !== 'undefined'){ | |
fAction += CTF.addTableItem("Effect = " + wepeffect); | |
} | |
if (typeof wepprofiles !== 'undefined'){ | |
sublist = ""; | |
wepprofiles.forEach((profile) => { | |
fAction += CTF.addTableItem(profile.name + " Profile = ----------" ); | |
if(typeof profile.on_attack !== 'undefined'){ | |
fAction += CTF.addTableItem(profile.name + ' On Attack = ' + profile.on_attack); | |
} | |
if(typeof profile.range !== 'undefined'){ | |
sublist = ""; | |
profile.range.forEach((rangetype)=>{ | |
sublist += rangetype.type + " **" + rangetype.val + "**<br>"; | |
}) | |
fAction += CTF.addTableItem(profile.name + " Range = " + sublist); | |
} | |
if(typeof profile.damage !== 'undefined'){ | |
profile.damage.forEach((damtype)=>{ | |
// WEIRD BARBAROSSA WORKAROUND | |
fAction += CTF.addTableItem(profile.name + " Damage = " + ((typeof damtype.type !== 'undefined') ? damtype.type : "") + ((damtype.val !== "N/A") ? " [[" + damtype.val + "]]" : "N/A")); | |
}) | |
} | |
if (typeof profile.effect !== 'undefined'){ | |
fAction += CTF.addTableItem(profile.name + " Effect = " + profile.effect); | |
} | |
if (typeof profile.actions !== 'undefined'){ | |
profile.actions.forEach((profileaction) => { | |
fAction += CTF.addTableItem(profileaction.name + "<br>" + CTF.addTableButton(profileaction.activation) + " = " + ((typeof profileaction.trigger !== 'undefined') ? "**Trigger** - " + profileaction.trigger + "<br>" : "") + profileaction.detail); | |
if (typeof profileaction.effect !== 'undefined'){ | |
fAction += CTF.addTableItem("Effect = " + profileaction.effect); | |
} | |
}); | |
} | |
if (typeof profile['tags'] !== 'undefined'){ | |
sublist = ""; | |
profile['tags'].forEach((profiletag)=>{ | |
let tagInfo = FindPcFeatureById(profiletag.id,'tag'); | |
sublist += CTF.addTableButton(((typeof profiletag.val !== 'undefined') ? tagInfo.name.replace("{VAL}", profiletag.val) : tagInfo.name)); | |
}) | |
fAction += CTF.addTableItem(profile.name + " Tags =" + sublist); | |
sublist = ""; | |
} | |
}) | |
} | |
if (typeof wepactions !== 'undefined'){ | |
wepactions.forEach((action) =>{ | |
fAction += CTF.addTableItem(action.name + "<br>" + CTF.addTableButton(action.activation) + " = " + action.detail); | |
}) | |
} | |
if (typeof weptags !== 'undefined'){ | |
sublist = ""; | |
weptags.forEach((tag) => { | |
let tagInfo = FindPcFeatureById(tag.id,'tag'); | |
sublist += CTF.addTableButton(((typeof tag.val !== 'undefined') ? tagInfo.name.replace("{VAL}", tag.val) : tagInfo.name), "!lcp_builder_pc_add_macro " + tag.id + " tag false"); | |
}) | |
fAction += CTF.addTableItem("Tags = " + sublist); | |
} | |
break; | |
case 'talent': | |
fId = desiredFeature["id"]; | |
fName = desiredFeature["name"]; | |
fEffect = desiredFeature["effect"]; | |
fActions = desiredFeature["actions"]; | |
fTags = desiredFeature["tags"]; | |
let talentRanks = desiredFeature["ranks"]; | |
subList = ""; | |
fAction = CTF.addTemplate() | |
+ CTF.addTableHeader(fName + " " + CTF.addTableButton("Add To Sheet", "!lcp_builder_pc_add_macro " + fId + " " + type)) | |
+ ((typeof fEffect !== 'undefined') ? CTF.addTableItem("Effect = " + fEffect) : ""); | |
if(typeof talentRanks !== 'undefined'){ | |
sublist = ""; | |
let talentitr = 0; | |
talentRanks.forEach((rank) => { | |
talentitr++; | |
fAction += CTF.addTableItem("Rank " + talentitr + "<br>" + rank.name + " = --------------------<br>" + rank['description']); | |
if (typeof rank.actions !== 'undefined'){ | |
rank.actions.forEach((action)=>{ | |
if (typeof action.activation != 'undefined'){ | |
sublist += "<br>" | |
+ CTF.addTableButton(action.activation) | |
+ ((typeof action.frequency !== 'undefined') ? "<br>" + CTF.addTableButton(action.frequency) : "") | |
+ " = " | |
+ ((typeof action.trigger !== 'undefined') ? "**Trigger** - " + action.trigger + "<br>": "") | |
+ ((typeof action.detail !== 'undefined') ? action.detail : "") | |
} | |
fAction += CTF.addTableItem(action.name + sublist); | |
sublist = ""; | |
}) | |
} | |
}) | |
} | |
break; | |
case 'corebonus': | |
fId = desiredFeature["id"]; | |
fName = desiredFeature["name"]; | |
fSource = desiredFeature["source"]; | |
fEffect = desiredFeature["effect"]; | |
fActions = desiredFeature["actions"]; | |
fTags = desiredFeature["tags"]; | |
subList = ""; | |
fAction = CTF.addTemplate() | |
+ CTF.addTableHeader(fName + " " + CTF.addTableButton("Add To Sheet", "!lcp_builder_pc_add_macro " + fId + " " + type)) | |
+ ((typeof fEffect !== 'undefined') ? CTF.addTableItem("Effect = " + fEffect) : ""); | |
if (typeof fActions !== 'undefined'){ | |
fActions.forEach((action) =>{ | |
let actiontrigger = action.trigger; | |
fAction += CTF.addTableItem(((typeof action.name !== 'undefined') ? action.name + "<br>" : "") + CTF.addTableButton(action.activation) + " = " + ((typeof actiontrigger !== 'undefined') ? "**Trigger** - " + actiontrigger + "<br>" : "") + action.detail); | |
}) | |
} | |
if (typeof fTags !== 'undefined'){ | |
sublist = ""; | |
fTags.forEach((tag) => { | |
let tagInfo = FindPcFeatureById(tag.id,'tag'); | |
sublist += CTF.addTableButton(((tag.val !== 'undefined') ? tagInfo.name.replace("{VAL}", tag.val) : tagInfo.name), "!lcp_builder_pc_add_macro " + tag.id + " tag false"); | |
}) | |
fAction += CTF.addTableItem("Tags = " + sublist); | |
} | |
break; | |
break; | |
default: | |
break; | |
} | |
if(displayOnly){ | |
sendChat("LCP BUILDER", fAction); | |
} | |
else{ | |
createObj("ability", { | |
name: fName, | |
characterid: characterID, | |
description: "a description", | |
action: fAction, | |
istokenaction: true | |
}); | |
} | |
} | |
function CleanTokenOfAllAbilities(msg){ | |
if (typeof msg.selected === 'undefined'){ | |
log("selected was undefined."); | |
return; | |
} | |
let obj = getObj(msg.selected[0]._type,msg.selected[0]._id); | |
let characterID = obj.get('represents'); | |
let charAbilities = findObjs({_characterid: characterID, _type: 'ability'}); | |
charAbilities.forEach((ability) => { | |
ability.remove(); | |
}) | |
} | |
function ImportPcCharacter(msg, rawstring){ | |
// First, Sanitize inputs | |
sendChat("IMPORT ACTION", "**PROCESSING RAW INPUT**") | |
var jsonObj = {}; | |
// First, pull in the mech name from the headline | |
log("IMPORTING MECH, BEGINNING PULL"); | |
let mechIndex = rawstring.indexOf(" ", 3)+1; | |
jsonObj.parsedMech = rawstring.substring(mechIndex, rawstring.indexOf(" @")); | |
// Pull in core bonuses | |
let bonusIndex = rawstring.indexOf("[ core bonuses ]"); | |
let bonusOffset = 16+1; | |
let parsedBonuses = rawstring.substring(bonusIndex+bonusOffset, rawstring.indexOf(" [ ", bonusIndex+bonusOffset)); | |
jsonObj.parsedBonuses = parsedBonuses.split(', '); | |
// Pull in Talents | |
let talentsIndex = rawstring.indexOf(" [ talents ]"); | |
let talentsOffset = 11+2; | |
let parsedTalents = rawstring.substring(talentsIndex+talentsOffset, rawstring.indexOf(" [ ", talentsIndex+talentsOffset)); | |
parsedTalents = parsedTalents.replaceAll(/ \d/g,""); | |
jsonObj.parsedTalents = parsedTalents.split(', '); | |
// Pull in Weapons | |
let weaponsIndex = rawstring.indexOf("[ weapons ]"); | |
let weaponsOffset = 11+1; | |
let parsedWeapons = rawstring.substring(weaponsIndex+weaponsOffset, rawstring.indexOf(" [ ", weaponsIndex+weaponsOffset)); | |
let tempWeapons = parsedWeapons; | |
while (tempWeapons.includes('main mount: ')){ | |
tempWeapons = tempWeapons.replaceAll(/main mount: /g, ','); | |
} | |
//log("Removed integrated mounts and replaced with commas. STRING:" + tempWeapons); | |
while (tempWeapons.includes('integrated: ')){ | |
tempWeapons = tempWeapons.replace('integrated: ', ','); | |
} | |
while (tempWeapons.includes('integrated weapon: ')){ | |
tempWeapons = tempWeapons.replace('integrated weapon: ', ','); | |
} | |
while (tempWeapons.includes('aux/aux mount: ')){ | |
tempWeapons = tempWeapons.replace('aux/aux mount: ', ','); | |
} | |
//log("Removed aux/aux mounts and replaced with commas. STRING:" + tempWeapons); | |
while (tempWeapons.includes('main/aux mount: ')){ | |
tempWeapons = tempWeapons.replace('main/aux mount: ', ','); | |
} | |
//log("Removed main/aux mounts and replaced with commas. STRING:" + tempWeapons); | |
while (tempWeapons.includes('flex mount: ')){ | |
tempWeapons = tempWeapons.replace('flex mount: ', ','); | |
} | |
//log("Removed flex mounts and replaced with commas. STRING:" + tempWeapons); | |
while (tempWeapons.includes('heavy mount: ')){ | |
tempWeapons = tempWeapons.replace('heavy mount: ', ','); | |
} | |
//log("Removed heavy mounts and replaced with commas. STRING:" + tempWeapons); | |
while (tempWeapons.includes(' / ')){ | |
tempWeapons = tempWeapons.replace(' / ', ' ,'); | |
} | |
//log("Removed Split mounts and replaced with commas. STRING:" + tempWeapons); | |
//Remove leading comma | |
tempWeapons = tempWeapons.substring(1); | |
let activeItem = ""; | |
let tempArry = tempWeapons.split(" ,"); | |
jsonObj.parsedMods = ""; | |
log("JSON prior to weapon fix:" + tempArry); | |
for (weapon in tempArry){ | |
log("PARSING WEAPON:" + tempArry[weapon]); | |
activeItem = weapon; | |
//Note and remove mods | |
//Erase any equipped core bonuses. We don't need that info. | |
if (tempArry[weapon].includes(' // ')){ | |
activeItem = tempArry[weapon].substring(0,tempArry[weapon].indexOf(' // ')); | |
log("WEAPON W/O CORE BONUSES: " + activeItem); | |
} | |
//Take note of equipped mods | |
if (tempArry[weapon].includes(' (')){ | |
log("ENTERED MOD LOGIC"); | |
let mod = ""; | |
// Carveout for these silly things | |
if (tempArry[weapon].includes('(hunter-killer)') || tempArry[weapon].includes('(light)')){ | |
log("CARVEOUT gms nexus"); | |
log(activeItem); | |
let tempstring = activeItem.substring(activeItem.indexOf(')')+1); | |
let actualObject = activeItem.substring(0,activeItem.indexOf(')')+1); | |
log(tempstring); | |
log("ACTUAL WEAPON:"+actualObject); | |
if (tempstring.includes('(') ) | |
{ | |
mod = tempstring.substring(tempstring.indexOf('(')+1,tempstring.indexOf(')')); | |
log(mod); | |
if (!jsonObj.parsedMods.includes(mod)){ | |
jsonObj.parsedMods = jsonObj.parsedMods + "," + mod; | |
} | |
} | |
tempArry[weapon] = actualObject; | |
} else { | |
mod = tempArry[weapon].substring(tempArry[weapon].indexOf('(')+1,tempArry[weapon].indexOf(')')); | |
let wep = tempArry[weapon].substring(0,tempArry[weapon].indexOf(' (')); | |
log(wep); | |
tempArry[weapon] = wep; | |
if (!jsonObj.parsedMods.includes(mod)){ | |
jsonObj.parsedMods = jsonObj.parsedMods + "," + mod; | |
} | |
} | |
} else { | |
// No mods were found. Add to list. | |
activeItem = weapon; | |
log("WEAPON NO FRILLS:"+activeItem); | |
} | |
//Fix the mods if mods were found | |
} | |
// If mods were found, we should have a list of mods by now. | |
log("PARSED MODS:"); | |
log(jsonObj.parsedMods); | |
if (jsonObj.parsedMods !== ""){ | |
log("FIXING MODS"); | |
jsonObj.parsedMods = jsonObj.parsedMods.substring(1); | |
// convert to array of strings | |
jsonObj.parsedMods = jsonObj.parsedMods.split(','); | |
log(jsonObj.parsedMods); | |
log("FIXED MODS"); | |
} | |
//Finally, copy each entry into the json obj, ignoring duplicates. | |
log("REMOVING DUPLICATE WEAPONS"); | |
jsonObj.parsedWeapons = []; | |
for (weapon in tempArry){ | |
if(!jsonObj.parsedWeapons.includes(tempArry[weapon])){ | |
jsonObj.parsedWeapons.push(tempArry[weapon]); | |
} | |
} | |
log("PARSING SYSTEMS"); | |
let systemsIndex = rawstring.indexOf("[ systems ]"); | |
let systemsOffset = 11+1; | |
let parsedSystems = rawstring.substring(systemsIndex+systemsOffset); | |
jsonObj.parsedSystems = parsedSystems.split(", "); | |
log("SYSTEMS:" + jsonObj.parsedSystems); | |
// The object is now prepped. Now start adding features to the character sheet. | |
log("ADDING FRAME IF ANY"); | |
if (typeof jsonObj.parsedMech !== 'undefined'){ | |
log("DEBUG FRAME: " + jsonObj.parsedMech); | |
let searchFrame = FindPcFrameByName(jsonObj.parsedMech) | |
if (typeof searchFrame !== 'undefined'){ | |
AddPcFeature(msg, searchFrame.id, 'frame', false); | |
} | |
} | |
log("ADDING CORE BONUSES IF ANY"); | |
if (typeof jsonObj.parsedBonuses !== 'undefined'){ | |
log("DEBUG BONUSES: " + jsonObj.parsedBonuses); | |
let searchBonus = ""; | |
jsonObj.parsedBonuses.forEach((bonus)=>{ | |
searchBonus = FindPcCoreBonusByName(bonus); | |
if (typeof searchBonus !== 'undefined'){ | |
AddPcFeature(msg, searchBonus.id, 'corebonus', false); | |
} | |
}); | |
} | |
log("ADDING TALENTS IF ANY"); | |
if (typeof jsonObj.parsedTalents !== 'undefined'){ | |
let searchTalent = ""; | |
jsonObj.parsedTalents.forEach((talent)=>{ | |
searchTalent = FindPcTalentByName(talent); | |
if (typeof searchTalent !== 'undefined'){ | |
AddPcFeature(msg, searchTalent.id, 'talent', false); | |
} | |
}); | |
} | |
log("ADDING WEAPONS IF ANY"); | |
if (typeof jsonObj.parsedWeapons !== 'undefined'){ | |
log("CURRENT WEAPONS:"+jsonObj.parsedWeapons); | |
let searchWeapon = ""; | |
jsonObj.parsedWeapons.forEach((weapon)=>{ | |
searchWeapon = FindPcWeaponByName(weapon); | |
log(searchWeapon); | |
if(typeof searchWeapon !== 'undefined'){ | |
AddPcFeature(msg,searchWeapon.id, 'weapon', false); | |
} | |
}); | |
} | |
log("ADDING MODS IF ANY"); | |
if (typeof jsonObj.parsedMods !== 'undefined'){ | |
let searchMod = ""; | |
//log("ADDING MODS TO SHEET"); | |
//log(jsonObj.parsedMods); | |
jsonObj.parsedMods.forEach((mod)=>{ | |
searchMod = FindPcModByName(mod); | |
//log(searchMod); | |
if(typeof searchMod !== 'undefined'){ | |
AddPcFeature(msg,searchMod.id, 'mod', false); | |
} | |
}); | |
} | |
log("ADDING SYSTEMS IF ANY"); | |
if (typeof jsonObj.parsedSystems !== 'undefined'){ | |
let searchSystem = ""; | |
jsonObj.parsedSystems.forEach((system)=>{ | |
searchSystem = FindPcSystemByName(system); | |
if(typeof searchSystem !== 'undefined'){ | |
AddPcFeature(msg, searchSystem.id, 'system', false); | |
} | |
}); | |
} | |
//Concat the strings that matter. while converting them into the format for the changeloadout call. | |
} | |
function injectScanData(msg, newabilityid, featuretype, tier){ | |
if (typeof msg.selected === 'undefined'){ | |
log("selected was undefined."); | |
return; | |
} | |
let obj = getObj(msg.selected[0]._type,msg.selected[0]._id); | |
let characterID = obj.get('represents'); | |
let charAbilities = findObjs({_characterid: characterID, _type: 'ability'}); | |
charAbilities.forEach((ability) => { | |
log("CHECK IF SCAN DATA"); | |
if (ability.get('name') === 'scan-data'){ | |
log("ENTERED SCAN DATA"); | |
let abilityaction = ability.get('action'); | |
log(abilityaction); | |
let of = /Optional Features = /; | |
let bf = /Base Features = /; | |
let tf = /Template Features = /; | |
let bfMatch = abilityaction.match(bf); | |
let ofMatch = abilityaction.match(of); | |
let tfMatch = abilityaction.match(tf); | |
log(newabilityid); | |
let featuretoadd = FindNpcFeature(newabilityid); | |
log(featuretoadd); | |
if (typeof featuretoadd === 'undefined'){ | |
log("INVALID FEATURE"); | |
return; | |
} | |
if (featuretoadd["origin"]["base"] == true){ | |
if (bfMatch === null) { // if no Optional on scan-data, create | |
abilityaction += CTF.addTableItem("Base Features = " + CTF.addTableButton(featuretoadd.name,"!lcp_builder_display_npc_feature " + newabilityid + " " + tier)); | |
ability.set('action', abilityaction); | |
} else { | |
let actionSplit = abilityaction.split(bf); | |
let reassembledstring = actionSplit[0] | |
+ "Base Features = " + CTF.addTableButton(featuretoadd.name,"!lcp_builder_display_npc_feature " + newabilityid + " " + tier) | |
+ actionSplit[1]; | |
ability.set('action', reassembledstring); | |
} | |
} | |
if (featuretoadd["origin"]["base"] == false){ | |
if (ofMatch === null) { // if no Optional on scan-data, create | |
abilityaction += CTF.addTableItem("Optional Features = " + CTF.addTableButton(featuretoadd.name,"!lcp_builder_display_npc_feature " + newabilityid + " " + tier)); | |
ability.set('action', abilityaction); | |
} else { // else, inject the new feature at the start. | |
let actionSplit = abilityaction.split(of); | |
let reassembledstring = actionSplit[0] | |
+ "Optional Features = " + CTF.addTableButton(featuretoadd.name,"!lcp_builder_display_npc_feature " + newabilityid + " " + tier) | |
+ actionSplit[1]; | |
ability.set('action', reassembledstring); | |
} | |
} | |
if (featuretype == "Template"){ | |
if (tfMatch === null) { // if no Template on scan-data, create | |
abilityaction += CTF.addTableItem("Template Features = " + CTF.addTableButton(featuretoadd.name,"!lcp_builder_display_npc_feature " + newabilityid + " " + tier)); | |
ability.set('action', abilityaction); | |
} else { // else, inject the new feature at the start. | |
let actionSplit = abilityaction.split(tf); | |
let reassembledstring = actionSplit[0] | |
+ "Template Features = " + CTF.addTableButton(featuretoadd.name,"!lcp_builder_display_npc_feature " + newabilityid + " " + tier) | |
+ actionSplit[1]; | |
ability.set('action', reassembledstring); | |
} | |
} | |
} | |
}) | |
} | |
function AddNpcClassFeature(msg, id, tier, displayOnly = false){ | |
let adjustedTier = tier-1; | |
if (typeof msg.selected === 'undefined') { | |
sendChat("LANCER CORE HELPER", "&{template:default}{{name=NO TOKEN SELECTED}}{{You must select a token for this macro}}"); | |
return; | |
} | |
let obj = getObj(msg.selected[0]._type,msg.selected[0]._id); | |
let characterID = obj.get('represents'); | |
let tokobj = getObj('graphic', msg.selected[0]._id); | |
let tokenName = tokobj.get('name').toLowerCase(); | |
if (!displayOnly) { sendChat("LCP BUILDER", "Adding " + id + " to " + tokenName); } | |
let desiredFeature = FindNpcFeature(id, tier); | |
if (typeof desiredFeature === 'undefined'){ | |
sendChat("LCP BUILDER", "Feature Not Found in Data Set. ID: "+id); | |
return; | |
} | |
let fName = desiredFeature["name"]; | |
let fType = desiredFeature["type"]; | |
let fOrigin = desiredFeature["origin"]["name"]; | |
let fEffect = desiredFeature["effect"]; | |
let fTags = desiredFeature["tags"]; | |
log("Name: "+ fName + " Type: " + fType + " Origin: " + " Effect: " + fEffect + " Tags: " + fTags); | |
let fAction = CTF.addTemplate() | |
+ CTF.addTableHeader(fName) | |
+ CTF.addTableItem("Origin = " + fOrigin) | |
+ CTF.addTableItem("Type = " + fType); | |
if (fType.toLowerCase() === "reaction"){ | |
fAction += CTF.addTableItem("Trigger = " + desiredFeature["trigger"]); | |
} | |
if (fType.toLowerCase() === "weapon"){ | |
fAction += CTF.addTableItem("Mount =" + desiredFeature["weapon_type"]); | |
desiredFeature["range"].forEach((rangetype) => { | |
fAction += CTF.addTableItem(rangetype.type + "=" + rangetype.val); | |
}); | |
log("ATTACK BONUS"); | |
let fAttackBonus = desiredFeature["attack_bonus"][adjustedTier]; | |
if (!(typeof desiredFeature["accuracy"] === 'undefined')){ | |
fAction += CTF.addTableItem("Accuracy = " + desiredFeature["accuracy"][adjustedTier]); | |
} | |
fAction += CTF.addTableItem("Attack Roll = **[[1d20+" + fAttackBonus + "]] | ACC/DIFF [[1d6]][[1d6]][[1d6]][[1d6]][[1d6]][[1d6]]**"); | |
let damstring = ""; | |
desiredFeature["damage"].forEach((damtype) => { | |
damstring += CTF.addTableButton(damtype.type + " " + damtype.damage[adjustedTier], "!lcp_chart_harm " + damtype.damage[adjustedTier] + " " + damtype.type); | |
}); | |
fAction += CTF.addTableItem("Damage =" + damstring); | |
} | |
if (fType.toLowerCase() === "tech"){ | |
if (!(typeof desiredFeature["attack_bonus"] === 'undefined')){ | |
let fAttackBonus = desiredFeature["attack_bonus"][adjustedTier]; | |
fAction += CTF.addTableItem("Attack Roll = **[[1d20+" + fAttackBonus + "]] | ACC/DIFF [[1d6]][[1d6]][[1d6]][[1d6]][[1d6]][[1d6]]**"); | |
} | |
} | |
if (!(typeof fEffect === 'undefined')){ | |
fAction += CTF.addTableItem("Effect = " + fEffect); | |
} | |
let onhit = ""; | |
if (!(typeof desiredFeature["on_hit"] === 'undefined')){ | |
fAction += CTF.addTableItem("On Hit = " + desiredFeature["on_hit"]); | |
} | |
log("TAGS"); | |
tagstring = ""; | |
if (!(typeof fTags === 'undefined')){ | |
fTags.forEach((tag) => { | |
log(tag); | |
if (tag.id == "tg_round" || tag.id == "tg_turn" || tag.id == "tg_scene"){ | |
tagstring += CTF.addTableButton(tag.val+"/"+tag.id.substring(3)); | |
} | |
else if (tag.id == "tg_recharge"){ | |
tagstring += CTF.addTableButton(tag.id.substring(3) + " " + tag.val + "+"); | |
} | |
else { | |
let tagvalue = (typeof tag.val === 'undefined') ? "" : " " + tag.val; | |
tagstring += CTF.addTableButton(tag.id.substring(3) + tagvalue); | |
} | |
}); | |
} | |
fAction += CTF.addTableItem("Tags = " + tagstring); | |
if(displayOnly){ | |
sendChat("LCP BUILDER", fAction); | |
} | |
else{ | |
createObj("ability", { | |
name: fName, | |
characterid: characterID, | |
description: "a description", | |
action: fAction, | |
istokenaction: true | |
}); | |
injectScanData(msg, id, adjustedTier); | |
} | |
} | |
function BuildTemplate(msg, templateName, tier, displayTemplate = false){ | |
let adjustedTier = tier-1; | |
if (typeof msg.selected === 'undefined') { | |
sendChat("LCP BUILDER", CTF.addTemplate()+CTF.addHeader("Error adding Template")+CTF.addTableItem("You must select a token to add or view a template.")); | |
return; | |
} | |
let obj = getObj(msg.selected[0]._type,msg.selected[0]._id); | |
let characterID = obj.get('represents'); | |
let npcTemplate = FindNpcTemplate(templateName); | |
if (typeof npcTemplate === 'undefined'){ | |
sendChat("LCP BUILDER", "Could not find template named "+ templateName + " in npcClassDataSet. Searched " + npcTemplateDataSet.length + " Sets."); | |
return; | |
} | |
// Get the token name | |
let tokobj = getObj('graphic', msg.selected[0]._id); | |
let tokenName = tokobj.get('name').toLowerCase(); | |
let basefeatures = npcTemplate["base_features"]; | |
let accumulatedBaseFeatures = ""; | |
basefeatures.forEach((element) => { | |
let tempFeature = FindNpcFeature(element, adjustedTier); | |
let addOrDisplay = (!displayTemplate) ? "!lcp_builder_display_npc_feature" : "!lcp_builder_add_npc_feature"; | |
accumulatedBaseFeatures += CTF.addTableButton(tempFeature["name"], addOrDisplay + " " + element + " " + tier); | |
}); | |
let optionalfeatures = npcTemplate["optional_features"]; | |
let accumulatedOptionalFeatures = ""; | |
optionalfeatures.forEach((element) => { | |
let tempFeature = FindNpcFeature(element, adjustedTier); | |
let addOrDisplay = (!displayTemplate) ? "!lcp_builder_display_npc_feature" : "!lcp_builder_add_npc_feature"; | |
accumulatedOptionalFeatures += CTF.addTableButton(tempFeature["name"], addOrDisplay + " " + element + " " + tier); | |
}); | |
// Define the card action for the character sheet ability | |
let MechCardAction = CTF.addTemplate(); | |
MechCardAction += (displayTemplate) ? CTF.addTableHeader(" Template Info " + CTF.addTableButton("ASSIGN","!lcp_builder_add_npc_template " + templateName + " " + tier)) : CTF.addTableHeader("scan-data"); | |
MechCardAction += CTF.addTableItem("Name = "+ templateName); | |
if(displayTemplate){ | |
MechCardAction += CTF.addTableItem("Base Features = "+ accumulatedBaseFeatures); | |
MechCardAction += CTF.addTableItem("Optional Features = "+ accumulatedOptionalFeatures); | |
} | |
if(displayTemplate){ | |
sendChat("LCP BUILDER", "/w gm " + MechCardAction); | |
return; | |
} | |
// else continue and attach all abilities from the base class. | |
basefeatures.forEach((element) => { | |
AddNpcClassFeature(msg, element, tier) | |
}); | |
} | |
function BuildClass(msg, className, tier, displayClass = false){ | |
// Get Selected Character | |
let adjustedTier = tier-1; | |
if (typeof msg.selected === 'undefined' && !displayClass) { | |
sendChat("LANCER CORE HELPER", "&{template:default}{{name=NO TOKEN SELECTED}}{{You must select a token for this macro}}"); | |
return; | |
} | |
let obj = getObj(msg.selected[0]._type,msg.selected[0]._id); | |
let characterID = obj.get('represents'); | |
let npcClass = FindNpcClass(className); | |
if (typeof npcClass === 'undefined'){ | |
sendChat("LCP BUILDER", "Could not find class named "+ className + " in npcClassDataSet. Searched " + npcClassDataSet.length + " Sets."); | |
return; | |
} | |
// Get the token name | |
let tokobj = getObj('graphic', msg.selected[0]._id); | |
let tokenName = tokobj.get('name').toLowerCase(); | |
let basefeatures = npcClass["base_features"]; | |
let accumulatedBaseFeatures = ""; | |
basefeatures.forEach((element) => { | |
let tempFeature = FindNpcFeature(element, adjustedTier); | |
let addOrDisplay = (!displayClass) ? "!lcp_builder_display_npc_feature" : "!lcp_builder_add_npc_feature"; | |
accumulatedBaseFeatures += CTF.addTableButton(tempFeature["name"], addOrDisplay + " " + element + " " + tier); | |
}); | |
let optionalfeatures = npcClass["optional_features"]; | |
let accumulatedOptionalFeatures = ""; | |
optionalfeatures.forEach((element) => { | |
let tempFeature = FindNpcFeature(element, adjustedTier); | |
let addOrDisplay = (!displayClass) ? "!lcp_builder_display_npc_feature" : "!lcp_builder_add_npc_feature"; | |
accumulatedOptionalFeatures += CTF.addTableButton(tempFeature["name"], addOrDisplay + " " + element + " " + tier); | |
}); | |
// Define the card action for the character sheet ability | |
let MechCardAction = CTF.addTemplate(); | |
MechCardAction += (displayClass) ? CTF.addTableHeader("Class Info " + CTF.addTableButton("ASSIGN","!lcp_builder_add_npc_class " + className + " " + tier)) : CTF.addTableHeader("scan-data"); | |
MechCardAction += (displayClass) ? "" : CTF.addTableItem("Name = "+ tokenName); | |
MechCardAction += CTF.addTableItem("Class = "+ npcClass["name"] + " TIER " + tier) | |
+ CTF.addTableItem("Vitals = "+ CTF.addTableButton("HP: " + "@{selected|bar1} / " + npcClass["stats"]["hp"][adjustedTier]) | |
+ CTF.addTableButton("HEAT: " + "@{selected|bar3} / " + npcClass["stats"]["heatcap"][adjustedTier]) | |
+ CTF.addTableButton("ARMOR: " + npcClass["stats"]["armor"][adjustedTier])) | |
+ CTF.addTableItem("Stats = "+ CTF.addTableButton("EVADE: " + npcClass["stats"]["evade"][adjustedTier]) | |
+ CTF.addTableButton("EDEF: " + npcClass["stats"]["edef"][adjustedTier]) | |
+ CTF.addTableButton("HASE: " | |
+ npcClass["stats"]["hull"][adjustedTier] + " / " | |
+ npcClass["stats"]["agility"][adjustedTier] + " / " | |
+ npcClass["stats"]["systems"][adjustedTier] + " / " | |
+ npcClass["stats"]["engineering"][adjustedTier]) | |
+ CTF.addTableButton("SAVE: " + npcClass["stats"]["save"][adjustedTier]) | |
+ CTF.addTableButton("SENSOR: " + npcClass["stats"]["sensor"][adjustedTier]) | |
+ CTF.addTableButton("SPEED: " + npcClass["stats"]["speed"][adjustedTier]) | |
+ CTF.addTableButton("SIZE: " + npcClass["stats"]["size"][adjustedTier])) | |
if(displayClass){ | |
MechCardAction += CTF.addTableItem("Base Features = "+ accumulatedBaseFeatures); | |
MechCardAction += CTF.addTableItem("Optional Features = "+ accumulatedOptionalFeatures); | |
} | |
if(displayClass){ | |
sendChat("LCP BUILDER", "/w gm " + MechCardAction); | |
return; | |
} | |
// else continue and attach all abilities from the base class. | |
createObj("ability", { | |
name: "scan-data", | |
characterid: characterID, | |
description: "a description", | |
action: MechCardAction, | |
istokenaction: true | |
}); | |
basefeatures.forEach((element) => { | |
AddNpcClassFeature(msg, element, tier) | |
}); | |
} | |
// DAMAGE CALCULATION AND APPLICATION | |
function ChartHarm(msg, harm, type){ | |
var message = CTF.addTemplate() + CTF.addTableHeader("INCOMING HARM - " + type.toUpperCase()); | |
let initialHarm = parseInt(harm); | |
let exposedHarm = parseInt(harm) * 2; | |
let ZeroComparator = function(left,right){ | |
return (left+right > 0) ? left+right : 0; | |
} | |
message += CTF.addTableItem("Raw Damage = " | |
+ CTF.addTableButton("Raw " + initialHarm, "!lcp_do_harm " + initialHarm + " " + type) | |
+ CTF.addTableButton("Exposed " + exposedHarm, "!lcp_do_harm " + exposedHarm + " " + type) | |
+ CTF.addTableButton("Resisted " + Math.ceil(initialHarm/2), "!lcp_do_harm " + Math.ceil(initialHarm/2) + " " + type)); | |
message += CTF.addTableItem("ARMOR = **1 | 2 | 3 | 4 | 5 | 6**") | |
message += CTF.addTableItem("Armored = " | |
+ CTF.addTableButton( (ZeroComparator(initialHarm,-1)), "!lcp_do_harm " + (ZeroComparator(initialHarm,-1)) + " " + type) | |
+ CTF.addTableButton( (ZeroComparator(initialHarm,-2)), "!lcp_do_harm " + (ZeroComparator(initialHarm,-2)) + " " + type) | |
+ CTF.addTableButton( (ZeroComparator(initialHarm,-3)), "!lcp_do_harm " + (ZeroComparator(initialHarm,-3)) + " " + type) | |
+ CTF.addTableButton( (ZeroComparator(initialHarm,-4)), "!lcp_do_harm " + (ZeroComparator(initialHarm,-4)) + " " + type) | |
+ CTF.addTableButton( (ZeroComparator(initialHarm,-5)), "!lcp_do_harm " + (ZeroComparator(initialHarm,-5)) + " " + type) | |
+ CTF.addTableButton( (ZeroComparator(initialHarm,-6)), "!lcp_do_harm " + (ZeroComparator(initialHarm,-6)) + " " + type)); | |
message += CTF.addTableItem("Armored + Resisted = " | |
+ CTF.addTableButton( Math.ceil(((ZeroComparator(initialHarm,-1)) / 2)), "!lcp_do_harm " + Math.ceil((ZeroComparator(initialHarm,-1))/2) + " " + type) | |
+ CTF.addTableButton( Math.ceil(((ZeroComparator(initialHarm,-2)) / 2)), "!lcp_do_harm " + Math.ceil((ZeroComparator(initialHarm,-2))/2) + " " + type) | |
+ CTF.addTableButton( Math.ceil(((ZeroComparator(initialHarm,-3)) / 2)), "!lcp_do_harm " + Math.ceil((ZeroComparator(initialHarm,-3))/2) + " " + type) | |
+ CTF.addTableButton( Math.ceil(((ZeroComparator(initialHarm,-4)) / 2)), "!lcp_do_harm " + Math.ceil((ZeroComparator(initialHarm,-4))/2) + " " + type) | |
+ CTF.addTableButton( Math.ceil(((ZeroComparator(initialHarm,-5)) / 2)), "!lcp_do_harm " + Math.ceil((ZeroComparator(initialHarm,-5))/2) + " " + type) | |
+ CTF.addTableButton( Math.ceil(((ZeroComparator(initialHarm,-6)) / 2)), "!lcp_do_harm " + Math.ceil((ZeroComparator(initialHarm,-6))/2) + " " + type)); | |
message += CTF.addTableItem("Armored + Exposed = " | |
+ CTF.addTableButton( (ZeroComparator(exposedHarm,-1)), "!lcp_do_harm " + (ZeroComparator(exposedHarm,-1)) + " " + type) | |
+ CTF.addTableButton( (ZeroComparator(exposedHarm,-2)), "!lcp_do_harm " + (ZeroComparator(exposedHarm,-2)) + " " + type) | |
+ CTF.addTableButton( (ZeroComparator(exposedHarm,-3)), "!lcp_do_harm " + (ZeroComparator(exposedHarm,-3)) + " " + type) | |
+ CTF.addTableButton( (ZeroComparator(exposedHarm,-4)), "!lcp_do_harm " + (ZeroComparator(exposedHarm,-4)) + " " + type) | |
+ CTF.addTableButton( (ZeroComparator(exposedHarm,-5)), "!lcp_do_harm " + (ZeroComparator(exposedHarm,-5)) + " " + type) | |
+ CTF.addTableButton( (ZeroComparator(exposedHarm,-6)), "!lcp_do_harm " + (ZeroComparator(exposedHarm,-6)) + " " + type)); | |
message += CTF.addTableItem("Armored + Exposed + Resisted = " | |
+ CTF.addTableButton( Math.ceil(((ZeroComparator(exposedHarm,-1))/2)), "!lcp_do_harm " + Math.ceil((ZeroComparator(exposedHarm,-1))/2) + " " + type) | |
+ CTF.addTableButton( Math.ceil(((ZeroComparator(exposedHarm,-2))/2)), "!lcp_do_harm " + Math.ceil((ZeroComparator(exposedHarm,-2))/2) + " " + type) | |
+ CTF.addTableButton( Math.ceil(((ZeroComparator(exposedHarm,-3))/2)), "!lcp_do_harm " + Math.ceil((ZeroComparator(exposedHarm,-3))/2) + " " + type) | |
+ CTF.addTableButton( Math.ceil(((ZeroComparator(exposedHarm,-4))/2)), "!lcp_do_harm " + Math.ceil((ZeroComparator(exposedHarm,-4))/2) + " " + type) | |
+ CTF.addTableButton( Math.ceil(((ZeroComparator(exposedHarm,-5))/2)), "!lcp_do_harm " + Math.ceil((ZeroComparator(exposedHarm,-5))/2) + " " + type) | |
+ CTF.addTableButton( Math.ceil(((ZeroComparator(exposedHarm,-6))/2)), "!lcp_do_harm " + Math.ceil((ZeroComparator(exposedHarm,-6))/2) + " " + type)); | |
sendChat("LANCER CORE HELPER", message); | |
} | |
function DoHarm(msg, amount, type){ | |
// Harm is either physical or heat. Burn is physical harm with extra properties so not needed. | |
let actualType = ""; | |
if (type.toLowerCase() === "energy" | |
|| type.toLowerCase() === "explosive" | |
|| type.toLowerCase() === "kinetic" | |
|| type.toLowerCase() === "burn"){ | |
actualType = "physical"; | |
} | |
else { | |
actualType = "heat"; | |
} | |
try{ | |
let obj = getObj(msg.selected[0]._type,msg.selected[0]._id); | |
if (typeof obj === 'undefined'){ | |
sendChat("LANCER CORE HELPER","ERROR: No Character attached to Token."); | |
return; | |
} | |
let bar1_max = parseInt(obj.get('bar1_max')); | |
let bar1_current = parseInt(obj.get('bar1_value')); | |
let bar2_max = parseInt(obj.get('bar2_max')); | |
let bar2_current = parseInt(obj.get('bar2_value')); | |
let bar3_max = parseInt(obj.get('bar3_max')); | |
let bar3_current = parseInt(obj.get('bar3_value')); | |
log("\nbar1: " + bar1_current + " | " + bar1_max + "\n" | |
+ "bar2: " + bar2_current + " | " + bar2_max + "\n" | |
+ "bar3: " + bar3_current + " | " + bar3_max + "\n"); | |
let damagecounter = parseInt(amount); | |
let timesover = 0; | |
if (actualType === "physical"){ | |
// if there is a value for overshield, get rid of it first. | |
if (bar2_current !== "" || bar2_current > 0){ | |
// more overshield than damage? subtract damage and stop. | |
if (bar2_current > damagecounter){ | |
bar2_current -= damagecounter; | |
obj.set('bar2_value', bar2_current); | |
} else { | |
damagecounter -= bar2_current; | |
obj.set('bar2_value', 0); // zero out the field. | |
} | |
} | |
// Next affect actual hitpoints. Keep track of how many times it flips | |
bar1_current -= damagecounter; | |
if (bar1_current <= 0){ | |
while (bar1_current <= 0 ) { | |
bar1_current += bar1_max; | |
timesover++; | |
} | |
} | |
obj.set('bar1_value', bar1_current); // Set the new value; | |
let message = CTF.addTemplate() | |
+ CTF.addTableHeader(obj.get('name').toUpperCase() + " DAMAGED") | |
+ CTF.addTableItem("SUFFERED " + amount + " " + type.toUpperCase()) | |
+ CTF.addTableItem("STRUCTURED " + timesover + " TIMES"); | |
if (timesover > 0){ | |
message += CTF.addTableItem(CTF.addTableButton("ROLL STRUCTURE", "!lcp_structure_table")); | |
} | |
sendChat("LANCER CORE HELPER", message); | |
} else { | |
// Damage is heat, use the other bar | |
bar3_current += damagecounter; | |
while (bar3_current > bar3_max){ | |
bar3_current -= bar3_max; | |
timesover++; | |
} | |
obj.set('bar3_value', bar3_current); // Set the new value; | |
let message = CTF.addTemplate() | |
+ CTF.addTableHeader(obj.get('name').toUpperCase() + " DAMAGED") | |
+ CTF.addTableItem("SUFFERED " + amount + " " + type.toUpperCase()) | |
+ CTF.addTableItem("OVERHEATED " + timesover + " TIMES"); | |
if (timesover > 0) { | |
message += CTF.addTableItem(CTF.addTableButton("ROLL OVERHEAT", "!lcp_overheat_table")); | |
} | |
sendChat("LANCER CORE HELPER", message); | |
} | |
} catch (e) { | |
sendChat("LANCER CORE HELPER", "ERROR: Something went while calculating damage:" + e); | |
} | |
} | |
function RollStructureTable(msg){ | |
let message = CTF.addTemplate() | |
+ CTF.addTableHeader("STRUCTURE DAMAGE") | |
+ CTF.addTableItem("ROLL = [[1d6]][[1d6]][[1d6]][[1d6]][[1d6]][[1d6]]") | |
+ CTF.addTableItem("5 OR 6 = GLANCING BLOW<br>Emergency systems kick in and stabilize your mech. However, your mech is impaired until the end of your next turn.") | |
+ CTF.addTableItem("2, 3, OR 4 = SYSTEM TRAUMA<br>Parts of your mech are torn off by the damage. Roll a d6 [[1d6]]. <br>On a 1-3, all the weapons on one mount are destroyed. <br>On a 4-6, a system is destroyed. <br>You choose what’s destroyed, but systems or weapons with the limited tag and no charges left are not valid. <br>If there’s nothing left of one result, it becomes the other. <br>If there’s absolutely nothing left to destroy, this result becomes DIRECT HIT instead.") | |
+ CTF.addTableItem("1 = DIRECT HIT<br>This result has different outcomes depending on how much structure your mech has remaining.<ul><li>3+ - Your mech is stunned until the end of your next turn.</li><li>2 - Your mech must pass a hull check or be destroyed. Even on a successful check, your mech is stunned until the end of your next turn.</li><li>1 or lower - Your mech is destroyed.</li></ul>") | |
+ CTF.addTableItem("MULTIPLE 1'S = CRUSHING BLOW <br> Your mech is damaged beyond repair and is destroyed. You can still exit it as normal."); | |
sendChat("LANCER CORE HELPER", message); | |
} | |
function RollOverheatTable(msg){ | |
let message = CTF.addTemplate() | |
+ CTF.addTableHeader("OVERHEATING") | |
+ CTF.addTableItem("ROLL = [[1d6]][[1d6]][[1d6]][[1d6]][[1d6]][[1d6]]") | |
+ CTF.addTableItem("5 OR 6 = EMERGENCY SHUNT<br>Cooling systems recover and manage to contain the peaking heat levels. However, your mech is impaired until the end of your next turn.") | |
+ CTF.addTableItem("2, 3, OR 4 = POWER PLANT DESTABILIZE<br>Your mech’s power plant becomes unstable, ejecting jets of plasma. Your mech suffers from the exposed status (taking double damage) until it takes action to remove it.") | |
+ CTF.addTableItem("1 = MELTDOWN<br>This result has different outcomes depending on how much reactor stress your mech has remaining.<ul><li>3+ - Your mech becomes EXPOSED</li><li>2 - Roll an ENGINEERING check. On a success, your mech is EXPOSED; on a failure, it suffers a reactor meltdown after 1d6 of your turns (rolled by the GM). A reactor meltdown can be prevented by retrying the ENGINEERING check as a full action.</li><li>1 or lower - Your mech suffers a reactor meltdown at the end of your next turn.</li></ul>") | |
+ CTF.addTableItem("MULTIPLE 1'S = IRREVERSIBLE MELTDOWN <br> Your reactor goes critical. Your mech will suffer a reactor meltdown at the end of your next turn."); | |
sendChat("LANCER CORE HELPER", message); | |
} | |
// AUTOMATED MACRO CREATION | |
function LcpCreateMacros(msg){ | |
try { | |
let chatstring = "/w " + msg.who + " " + CTF.addTemplate() + CTF.addTableHeader("Generating Lancer Core Helper Macros"); | |
let numMacros = 0; | |
if (!playerIsGM(msg.playerid)){ | |
return; | |
} | |
if (!p_lncr_roll20objcontains("PC-Build-Menu")){ | |
createObj('macro', { | |
_playerid: msg.playerid, | |
name: "PC-Build-Menu", | |
action: "!lcp_builder_pc_menu", | |
visibleto: 'all', | |
istokenaction: true | |
}); | |
chatstring += "{{PC-Build-Menu}}"; | |
numMacros++; | |
} | |
if (!p_lncr_roll20objcontains('Clean-Selected-Token')){ | |
createObj('macro', { | |
_playerid: msg.playerid, | |
name: "Clean-Selected-Token", | |
action: "!lcp_builder_clean", | |
visibleto: '', | |
istokenaction: true | |
}); | |
chatstring += CTF.addTableItem("Clean-Selected-Token"); | |
numMacros++; | |
} | |
if (!p_lncr_roll20objcontains('NPC-Build-Menu')){ | |
createObj('macro', { | |
_playerid: msg.playerid, | |
name: "NPC-Build-Menu", | |
action: "!lcp_builder_display_class_menu", | |
visibleto: '', | |
istokenaction: false | |
}); | |
chatstring += "{{NPC-Build-Menu}}"; | |
numMacros++; | |
} | |
if (!p_lncr_roll20objcontains('NPC-Attack/Save')){ | |
createObj('macro', { | |
_playerid: msg.playerid, | |
name: "NPC-Attack/Save", | |
action: "&{template:default}{{name=NPC-Attack/Save}}{{Attack/Save = [[1d20]]}}{{ACC/DIFF = [[1d6]][[1d6]][[1d6]][[1d6]][[1d6]][[1d6]][[1d6]]}}", | |
visibleto: '', | |
istokenaction: false | |
}); | |
chatstring += "{{NPC-Attack/Save}}"; | |
numMacros++; | |
} | |
if (numMacros == 0) { | |
chatstring += "{{All macros are already defined}}"; | |
} | |
sendChat("LANCER CORE HELPER",chatstring); | |
}catch(e){ | |
sendChat("LANCER CORE HELPER", "Something went wrong while initializing."); | |
} | |
} | |
// COMMAND HANDLER | |
on('chat:message', function(msg){ | |
"use strict"; | |
if('api' !== msg.type) { | |
return; | |
} | |
var args = msg.content.split(/\s+/); | |
let stragg = function(startpos=1){ | |
let aggstring = "" | |
for (let i = startpos; i < args.length; i++) | |
{ | |
aggstring += args[i] | |
if (i+1 !== args.length){ | |
aggstring += " "; | |
} | |
} | |
return aggstring.toLowerCase(); | |
}; | |
switch (args[0]){ | |
case '!lcp_builder_pc_menu': | |
MenuPcOptionsList(msg); | |
break; | |
case '!lcp_builder_displaylist': | |
DisplayPcItemList(msg, args[1], args[2]); | |
break; | |
case '!lcp_builder_pc_add_macro': | |
AddPcFeature(msg, args[1], args[2], args[3]); | |
break; | |
case '!lcp_builder_clean': | |
sendChat("LCP BUILDER:", "Cleaning Token"); | |
CleanTokenOfAllAbilities(msg); | |
break; | |
case '!lcp_import_char': | |
sendChat("LCP IMPORTER", "Attepting to import character."); | |
let contents = stragg(); | |
ImportPcCharacter(msg, contents); | |
break; | |
case '!lcp_chart_harm': | |
ChartHarm(msg, args[1], args[2]); | |
break; | |
case '!lcp_do_harm': | |
DoHarm(msg, args[1], args[2]); | |
break; | |
case '!lcp_structure_table': | |
RollStructureTable(msg); | |
break; | |
case '!lcp_overheat_table': | |
RollOverheatTable(msg); | |
break; | |
case '!lcp_builder_display_class_menu': | |
MenuNpcClassTier(msg); | |
break; | |
case '!lcp_builder_add_npc_feature': | |
sendChat("LCP BUILDER", "Adding feature to selected token"); | |
AddNpcClassFeature(msg,args[1], parseInt(args[2])); | |
break; | |
case '!lcp_builder_display_npc_feature': | |
AddNpcClassFeature(msg,args[1], parseInt(args[2]), true); | |
break; | |
case '!lcp_builder_add_npc_class': | |
BuildClass(msg,args[1],parseInt(args[2]), args[3]); | |
break; | |
case '!lcp_builder_add_npc_template': | |
BuildTemplate(msg,args[1],parseInt(args[2]), args[3]); | |
break; | |
case '!lcp_builder_display_class_list': | |
sendChat("LCP BUILDER", "Attempting to parse JSON data from Classes LCP"); | |
DisplayClassList(msg, parseInt(args[1]), true); | |
break; | |
case '!lcp_builder_display_template_list': | |
sendChat("LCP BUILDER", "Attempting to parse JSON data from Templates LCP"); | |
DisplayTemplateList(msg, parseInt(args[1]), true); | |
break; | |
default: | |
break; | |
} | |
return; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment