Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Geiger Counter question?

Hey hive mind, I’ve got a question/request for anyone who thinks they can help.  I’m running a Fallout rpg, and love Stephen Lindberg’s Geiger Counter script for obvious reasons, but I have a couple of characters that are immune to radiation.  Similarly to how you can specify via an attribute that a character has a Geiger counter, would it be possible to add to the script such that it will not  post a radiation warning when a character that has something like a radiation_immunity attribute set to true?  Were I knowledgeable enough in scripting to write the addition myself, I would, but it is regretfully rather intimidating to get into.  Thanks in advance for any help! 
1637769623

Edited 1637784847
timmaugh
Pro
API Scripter
APILogic is a metascript that can help. (Hmm... I really need to post that metascript article to the wiki so I can point people to it as explanation.) =D Basically, metascripts get in the message and let you tweak it before it reaches the intended recipient script (in this case, the Geiger Counter script). In APILogic's case, it gives you the ability to have IF/ELSE branches in your command line. You could basically establish a message command line to Geiger Counter that would read (here rendered in High Common, not Old Syntactic): IF this character has Immunity to Radiation, do nothing, ELSE send the rest of this line to Geiger Counter to do its thing. Depending on how complex you need to get on retrieving things from the character, you might need ZeroFrame, SelectManager, and/or Fetch (all metascripts). If you post your example command line to Geiger Counter as well as the attribute or condition that would represent a character's immunity to radiation, I can help with putting the APIL constructions in.
1637867993
GiGs
Pro
Sheet Author
API Scripter
timmaugh said: (Hmm... I really need to post that metascript article to the wiki so I can point people to it as explanation.) =D Indeed you do...
1638491395

Edited 1638491522
timmaugh said: APILogic is a metascript that can help. (Hmm... I really need to post that metascript article to the wiki so I can point people to it as explanation.) =D Basically, metascripts get in the message and let you tweak it before it reaches the intended recipient script (in this case, the Geiger Counter script). In APILogic's case, it gives you the ability to have IF/ELSE branches in your command line. You could basically establish a message command line to Geiger Counter that would read (here rendered in High Common, not Old Syntactic): IF this character has Immunity to Radiation, do nothing, ELSE send the rest of this line to Geiger Counter to do its thing. Depending on how complex you need to get on retrieving things from the character, you might need ZeroFrame, SelectManager, and/or Fetch (all metascripts). If you post your example command line to Geiger Counter as well as the attribute or condition that would represent a character's immunity to radiation, I can help with putting the APIL constructions in. So, the script doesn't actually require chat input for commands on my part, it just registers (I think with the assistance of other API's) whenever a sheet-associated token is moved within the aura1 radius of a token in the GM layer with the radioactive status marker on it (as well as bar1 and bar1max values defined as the radiation levels), so I'm not sure how I would interrupt the scripts in order to use APILogic effectively. 
1638540581
David M.
Pro
API Scripter
I think this modified version might do what you are asking. Currently it looks for an attribute named "radiation_immunity", and will skip the GM whisper if the value of that attribute is either "true", "1", or "yes". You can change the name of that attribute on line 28 of the script var immunityAttrName = 'radiation_immunity'; It still creates a public chat msg if they have a Geiger counter. Only the GM whisper is affected. Does this work for you? /** * This script allows the GM to dynamically create radioactive areas in their * maps. Characters that have Geiger counters will be alerted how many rads * they are taking. * * To create a radioactive source object: * 1) Create a token representing the source on the GM layer. * 2) Set that token's 'radioactive' status marker to on. * 3) Set its aura1 radius to the distance at which characters will start * taking rads from it. * 4) Set the bar1 value to amount of rads/s characters will take at the edge * of its aura. * 5) Set the bar1 max value to the maximum amount of rads/s characters can take * from it. * * To give a player a Geiger counter: * 1) Give them a 'hasGeigerCounter' attribute. * 2) Set the attribute to 'true'. * * To make a character immune to radiation, set the attribute "radiation_immunity" to either "true", "1", or "yes" * * If a character moves in a radioactive area and they have a Geiger counter, * their Geiger counter will alert everyone how many rads/s they are taking. * If a character moves in a radioactive area and they don't have a Geiger * counter, only the GM will be alerted how many rads/s they are taking. */ var GeigerCounter = (function() { var immunityAttrName = 'radiation_immunity'; /** * Computes the apparent brightness of some object, given distance from it * and the object's luminosity. * @param {number} distance * @param {number} luminosity * @return {number} */ function getBrightness(distance, luminosity) { return luminosity/(4*Math.PI*distance*distance); } /** * Computes the luminosity of some object, given distance from it and the * apparent brightness of that object at that distance. * @param {number} distance * @param {number} brightness * @return {number} */ function getLuminosity(distance, brightness) { return brightness*4*Math.PI*distance*distance; } /** * Gets the unit scale for an object's page. * @param {graphic} The graphic whose page to get the scale for. * @return {number} */ function _getPageScale(obj) { var page = findObjs({ _type: 'page', _id: obj.get('_pageid') })[0]; return page.get('scale_number'); } /** * Gets all the tokens representing radioactive sources on the same map * that some other graphic is on. * @param {graphic} The graphic whose page to use. * @return {graphic[]} */ function getRadioactiveTokens(obj) { return findObjs({ _pageid: obj.get('_pageid'), _type: 'graphic', layer: 'gmlayer', status_radioactive: true }); } /** * Gets the amount of rads an object is taking from a radioactive token. * @param {graphic} A graphic representing a character * @param {graphic} A gmlayer graphic representing a radioactive source. * @return {int} */ function getRads(obj, radToken) { var pageScale = _getPageScale(obj); var maxDist = parseInt(radToken.get('aura1_radius')) + parseInt(radToken.get('width'))/70*pageScale; var minRads = parseInt(radToken.get('bar1_value')); var maxRads = parseInt(radToken.get('bar1_max')); if(!maxDist || !minRads || !maxRads) return 0; var x1 = obj.get('left'); var y1 = obj.get('top'); var x2 = radToken.get('left'); var y2 = radToken.get('top'); var dx = x1-x2; var dy = y1-y2; var distance = Math.sqrt(dx*dx + dy*dy); distance = distance/70*pageScale; if(distance === 0) return parseInt(maxRads); if(distance > maxDist) return 0; var luminosity = getLuminosity(maxDist, minRads); var brightness = getBrightness(distance, luminosity); return Math.min(maxRads, brightness); } /** * Checks if a character token has a geiger counter. * @param {graphic} A graphic representing a character. * @return {boolean} */ function hasGeigerCounter(obj) { var charId = obj.get('represents'); if(!charId) return false; var geigerAttr = findObjs({ _type: 'attribute', _characterid: charId, name: 'hasGeigerCounter' })[0]; return geigerAttr && geigerAttr.get('current'); } function _updateToken(obj) { // Only handle this script if the moved object represents a // player character. if(obj.get('represents')) { var character = findObjs({ _type: 'character', _id: obj.get('represents'), })[0]; let charName = character.get('name'); if (character) { let charID = character.get("_id"); //look for radiation_immunity attribute let attr = findObjs({ _type: "attribute", _characterid: charID, name: immunityAttrName }, {caseInsensitive: true})[0]; //check immunity value let isImmune = false; if (attr) { if (_.contains(['true','yes', '1'], attr.get('current').toLowerCase())) { isImmune = true; } } var radTokens = getRadioactiveTokens(obj); var rads = 0; // Get the total number of rads/s the character is taking on their // page from all radioactive sources. _.each(radTokens, function(radToken) { if(obj === radToken) return; rads += getRads(obj, radToken); }); // Round the total up for display. rads = Math.ceil(rads); if(rads) { // If the player has a Geiger counter, let everyone know that // they are taking rads. if(hasGeigerCounter(obj)) { sendChat('☢', charName + '\'s Geiger counter is ' + 'clicking at ' + rads + ' rads/s.'); // Otherwise, let only the GM know that they are taking rads. } else if (!isImmune) { sendChat('☢', '/w GM ' + charName + ' is taking ' + rads + ' rads/s.'); } } } } } on('change:graphic:lastmove', function(obj) { _updateToken(obj); }); // Expose the public functions as an API of this module. return { getBrightness: getBrightness, getLuminosity: getLuminosity, getRadioactiveTokens: getRadioactiveTokens, getRads: getRads, hasGeigerCounter: hasGeigerCounter }; })();
Yes! That is exactly the kind of thing I was looking/asking for! I really appreciate it David!