Skip to content

Instantly share code, notes, and snippets.

@shdwjk
Forked from Kurohyou/EasyExperience
Created April 28, 2016 21:52
Show Gist options
  • Save shdwjk/f4875b572ab7d2827e9868479a185678 to your computer and use it in GitHub Desktop.
Save shdwjk/f4875b572ab7d2827e9868479a185678 to your computer and use it in GitHub Desktop.
/*
Easy Experience Script:
This script will create a character called ExperienceThresholds that it uses for most of its functionality. If there is already an
ExperienceThresholds character present, it will not make one; please make sure that you do not have a self-made ExperienceThresholds character
(highly unlikely I would think ;) )
----------------------------------------------------------------------------------------
Use the following chat commands to utilize this script:
!xp challenge @{token_id/character_id}: Adds a character's npc-xp attribute value to the Session XP tally in the ExperienceThresholds character.
!xp miscXP ###: Adds a manually entered XP value to the Session XP tally in ExperienceThresholds.
!xp session: Divides the Session XP by the number of PCs (defined as characters that have a player-name entry), adds that xp to each PC's
current experience, and then sets the Session XP max field to the current field before resetting the current field to 0. Will also send
a chat message congratulating the character on leveling up if this brings that character's current
experience above or equal to the experience|max value.
----------------------------------------------------------------------------------------
The script will also automatically set the experience|max value of all PCs based on their current level, and will update this whenever their level
changes. Experience Thresholds can be updated by changing the threshold values (2-20) in ExperienceThresholds.
*/
var EASYEXPERIENCE = EASYEXPERIENCE || (function() {
'use strict';
var version = '0.0.2',
lastUpdate = 1461880298,
schemaVersion = 0.1,
ExperienceThresholds,
ch = function (c) {
var entities = {
'<' : 'lt',
'>' : 'gt',
"'" : '#39',
'@' : '#64',
'{' : '#123',
'|' : '#124',
'}' : '#125',
'[' : '#91',
']' : '#93',
'"' : 'quot',
'-' : 'mdash',
' ' : 'nbsp'
};
if(_.has(entities,c) ){
return ('&'+entities[c]+';');
}
return '';
},
checkInstall = function() {
log('-=> Character Experience v'+version+' <=- ['+(new Date(lastUpdate*1000))+']');
if( ! _.has(state,'EASYEXPERIENCE') || state.EASYEXPERIENCE.version !== schemaVersion) {
log(' > Updating Schema to v'+schemaVersion+' <');
state.EASYEXPERIENCE = {
version: schemaVersion,
config: {
},
policies: {
global: {
recoveryUpdatesMaximum: false
},
byAttribute: {
},
byCharacter: {
}
}
};
}
createThresholds();
},
playerCharacters = function() {
/* start the chain with all the attribute objects named 'player-name' */
return _.chain(filterObjs((o) => {
return (o.get('type')==='attribute' && o.get('name')==='player-name');
}))
//.tap((o)=>{log('chain started '+o.length);})
/* IN: Array of Attribute Objects */
/* extract the characterid from each */
.reduce((m,o)=>{
let obj={};
obj.cid=o.get('characterid');
obj['player-name']=o;
m.push(obj);
return m;
},[])
//.tap((o)=>{log('after .reduce '+ o.length);})
/* IN: Array of Objects with
* Character ID in property cid
* attribute in [attributeName]
*/
/* add characters to the objects */
.map((o)=>{
o.char=getObj('character',o.cid);
return o;
})
//.tap((o)=>{log('after character added '+o.length);})
/* IN: Array of Objects with
* Character ID in property cid
* attribute in [attributeName]
* character in property char
*/
/* remove any entries that didn't have Characters */
.reject( (o)=> {return _.isUndefined(o.char);} )
//.tap((o)=>{log('after .reject '+o.length);})
/*IN: Array of Objects cleaned of undefined characters
* with character ID's, 'player-name' attribute in ['player-name]
* and character in property char
****
* add the experience attribute to a property called xp for all characters*/
.map( (o)=>{
o.xp = findObjs({
type: 'attribute',
name: 'experience',
characterid: o.cid
})[0];
if(! o.xp.get('current')){
o.xp.set('current', 0);
}
return o;
})
/* IN: Array of Character Objects */
/* Unwrap Chain and return the array */
.value();
},
getThresholds = function(){
return _.chain(filterObjs((o) => {
return (o.get('type')==='attribute' && o.get('name')==='Session XP');
}))
.reduce((m,o)=>{
let obj={};
obj.cid=o.get('characterid');
obj['Session XP']=o;
m.push(obj);
return m;
},[])
.map((o)=>{
let attrs=filterObjs( (a)=>{
return a.get('type')==='attribute' && a.get('characterid')===o.cid &&
_.contains(['2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20'],a.get('name'));
});
o.attrs=o.attrs||{};
_.each(attrs, (a)=>{
o.attrs[a.get('name')]=a;
});
return o;
})
.value();
},
applyXP = function(){
var pcs = playerCharacters(),
thresholds = getThresholds(),
numPCs,
sessionXP,
eachTrack = parseInt(0);
sessionXP = parseInt(thresholds[0]['Session XP'].get('current'));
if(sessionXP>0){
numPCs = parseInt(pcs.length);
_.each(pcs, function(){
pcs[eachTrack].xp.set('current', parseInt(pcs[eachTrack].xp.get('current')) + sessionXP/numPCs);
if(pcs[eachTrack].xp.get('current')>=pcs[eachTrack].xp.get('max')){
sendChat('Congratulations! ' + pcs[eachTrack].char.get('name'), pcs[eachTrack].char.get('name') + ' has leveled up!');
}
eachTrack++;
});
thresholds[0]['Session XP'].set('max', thresholds[0]['Session XP'].get('current'));
thresholds[0]['Session XP'].set('current', 0);
}else{
sendChat('Experience Tracker', '/w gm There is currently no experience in the Session XP attribute of the tracker. No XP was applied and your previous Session XP was not overwritten.');
return;
}
},
recordXP = function(xpAward){
var thresholds=getThresholds(),
currXP;
currXP=parseInt(thresholds[0]['Session XP'].get('current'));
thresholds[0]['Session XP'].set('current', currXP + xpAward);
},
HandleInput = function(msg_orig) {
var msg = _.clone(msg_orig),
args,attr,amount,chr,token,text='';
if (msg.type !== 'api' || !playerIsGM(msg.playerid)){
return;
}
if(_.has(msg,'inlinerolls')){//calculates inline rolls
msg.content = _.chain(msg.inlinerolls)
.reduce(function(m,v,k){
m['$[['+k+']]']=v.results.total || 0;
return m;
},{})
.reduce(function(m,v,k){
return m.replace(k,v);
},msg.content)
.value();
}
args = msg.content.split(/\s+/);//splits the message contents into discrete arguments
switch(args[0]) {
case '!xp':
if(args.length > 1) {
switch(args[1]) {
case 'session':
applyXP();// <character/token_id> <attribute_name>
// apply policy to put amounts back in
break;
case 'challenge':
chr = getObj('character', args[2]);
if( ! chr ) {
token = getObj('graphic', args[2]);
if(token) {
chr = getObj('character', token.get('represents'));
}
}
if(chr) {
attr = findObjs({_type: 'attribute', _characterid: chr.id, name: 'npc-xp'})[0];
amount=parseInt(attr.get('current'));
}
if(attr) {
recordXP(amount);
}
break;
case 'miscXP':
amount = parseInt(args[2]);
if(amount){
recordXP(amount);
}
break;
}
} else {
sendChat('Experience', '/w gm Something went wrong');
}
break;
}
},
levelUP = function(level){
var thresholds = getThresholds(),
currXP = findObjs({
type: 'attribute',
name: 'experience',
characterid: level.get('characterid')
}),
nextLevel;
if(level.get('current')<20){
nextLevel = level.get('current') + 1;
currXP[0].set('max', thresholds[0].attrs[nextLevel].get('current'));
}
},
createThresholds = function(){
ExperienceThresholds = findObjs({
_type: "character",
name: "ExperienceThresholds"
})[0];
if (!ExperienceThresholds) {
ExperienceThresholds = createObj("character", {
name: "ExperienceThresholds"
});
let levels = {
"Session XP": 0,
"2": 2000,
"3": 5000,
"4": 9000,
"5": 15000,
"6": 23000,
"7": 35000,
"8": 51000,
"9": 75000,
"10": 105000,
"11": 155000,
"12": 220000,
"13": 315000,
"14": 445000,
"15": 635000,
"16": 890000,
"17": 1300000,
"18": 1800000,
"19": 2550000,
"20": 3600000
};
_.each(levels, (xp,lvl) => {
createObj('attribute',{
name: lvl,
current: xp,
characterid: ExperienceThresholds.id
});
});
}
},
RegisterEventHandlers = function() {
on('chat:message', HandleInput);
on('change:attribute:current',(a,p)=>{
if(a.get('name') === 'level'){
levelUP(a);
}
});
};
return {
CheckInstall: checkInstall,
RegisterEventHandlers: RegisterEventHandlers
};
}());
on("ready",function(){
'use strict';
EASYEXPERIENCE.CheckInstall();
EASYEXPERIENCE.RegisterEventHandlers();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment