path.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. var Path = {
  2. DEFAULT_BAG_SPACE: 10,
  3. _STORES_OFFSET: 0,
  4. // Everything not in this list weighs 1
  5. Weight: {
  6. 'bone spear': 2,
  7. 'iron sword': 3,
  8. 'steel sword': 5,
  9. 'rifle': 5,
  10. 'bullets': 0.1,
  11. 'energy cell': 0.2,
  12. 'laser rifle': 5,
  13. 'bolas': 0.5
  14. },
  15. name: 'Path',
  16. options: {}, // Nuthin'
  17. init: function(options) {
  18. this.options = $.extend(
  19. this.options,
  20. options
  21. );
  22. // Init the World
  23. World.init();
  24. // Create the path tab
  25. this.tab = Header.addLocation(_("A Dusty Path"), "path", Path);
  26. // Create the Path panel
  27. this.panel = $('<div>').attr('id', "pathPanel")
  28. .addClass('location')
  29. .appendTo('div#locationSlider');
  30. // Add the outfitting area
  31. var outfitting = $('<div>').attr({'id': 'outfitting', 'data-legend': _('supplies:')}).appendTo(this.panel);
  32. $('<div>').attr('id', 'bagspace').appendTo(outfitting);
  33. // Add the embark button
  34. new Button.Button({
  35. id: 'embarkButton',
  36. text: _("embark"),
  37. click: Path.embark,
  38. width: '80px',
  39. cooldown: World.DEATH_COOLDOWN
  40. }).appendTo(this.panel);
  41. Path.outfit = $SM.get('outfit');
  42. Engine.updateSlider();
  43. //subscribe to stateUpdates
  44. $.Dispatch('stateUpdate').subscribe(Path.handleStateUpdates);
  45. },
  46. openPath: function() {
  47. Path.init();
  48. Engine.event('progress', 'path');
  49. Notifications.notify(Room, _('the compass points ' + World.dir));
  50. },
  51. getWeight: function(thing) {
  52. var w = Path.Weight[thing];
  53. if(typeof w != 'number') w = 1;
  54. return w;
  55. },
  56. getCapacity: function() {
  57. if($SM.get('stores.convoy', true) > 0) {
  58. return Path.DEFAULT_BAG_SPACE + 60;
  59. } else if($SM.get('stores.wagon', true) > 0) {
  60. return Path.DEFAULT_BAG_SPACE + 30;
  61. } else if($SM.get('stores.rucksack', true) > 0) {
  62. return Path.DEFAULT_BAG_SPACE + 10;
  63. }
  64. return Path.DEFAULT_BAG_SPACE;
  65. },
  66. getFreeSpace: function() {
  67. var num = 0;
  68. if(Path.outfit) {
  69. for(var k in Path.outfit) {
  70. var n = Path.outfit[k];
  71. if(isNaN(n)) {
  72. // No idea how this happens, but I will fix it here!
  73. Path.outfit[k] = n = 0;
  74. }
  75. num += n * Path.getWeight(k);
  76. }
  77. }
  78. return Path.getCapacity() - num;
  79. },
  80. updatePerks: function(ignoreStores) {
  81. if($SM.get('character.perks')) {
  82. var perks = $('#perks');
  83. var needsAppend = false;
  84. if(perks.length === 0) {
  85. needsAppend = true;
  86. perks = $('<div>').attr({'id': 'perks', 'data-legend': _('perks:')});
  87. }
  88. for(var k in $SM.get('character.perks')) {
  89. var id = 'perk_' + k.replace(' ', '-');
  90. var r = $('#' + id);
  91. if($SM.get('character.perks["'+k+'"]') && r.length === 0) {
  92. r = $('<div>').attr('id', id).addClass('perkRow').appendTo(perks);
  93. $('<div>').addClass('row_key').text(_(k)).appendTo(r);
  94. $('<div>').addClass('tooltip bottom right').text(Engine.Perks[k].desc).appendTo(r);
  95. }
  96. }
  97. if(needsAppend && perks.children().length > 0) {
  98. perks.prependTo(Path.panel);
  99. }
  100. if(!ignoreStores && Engine.activeModule === Path) {
  101. $('#storesContainer').css({top: perks.height() + 26 + Path._STORES_OFFSET + 'px'});
  102. }
  103. }
  104. },
  105. updateOutfitting: function() {
  106. var outfit = $('div#outfitting');
  107. if(!Path.outfit) {
  108. Path.outfit = {};
  109. }
  110. // Add the armour row
  111. var armour = _("none");
  112. if($SM.get('stores["s armour"]', true) > 0)
  113. armour = _("steel");
  114. else if($SM.get('stores["i armour"]', true) > 0)
  115. armour = _("iron");
  116. else if($SM.get('stores["l armour"]', true) > 0)
  117. armour = _("leather");
  118. var aRow = $('#armourRow');
  119. if(aRow.length === 0) {
  120. aRow = $('<div>').attr('id', 'armourRow').addClass('outfitRow').prependTo(outfit);
  121. $('<div>').addClass('row_key').text(_('armour')).appendTo(aRow);
  122. $('<div>').addClass('row_val').text(armour).appendTo(aRow);
  123. $('<div>').addClass('clear').appendTo(aRow);
  124. } else {
  125. $('.row_val', aRow).text(armour);
  126. }
  127. // Add the water row
  128. var wRow = $('#waterRow');
  129. if(wRow.length === 0) {
  130. wRow = $('<div>').attr('id', 'waterRow').addClass('outfitRow').insertAfter(aRow);
  131. $('<div>').addClass('row_key').text(_('water')).appendTo(wRow);
  132. $('<div>').addClass('row_val').text(World.getMaxWater()).appendTo(wRow);
  133. $('<div>').addClass('clear').appendTo(wRow);
  134. } else {
  135. $('.row_val', wRow).text(World.getMaxWater());
  136. }
  137. var space = Path.getFreeSpace();
  138. var total = 0;
  139. // Add the non-craftables to the craftables
  140. var carryable = $.extend({
  141. 'cured meat': { type: 'tool' },
  142. 'bullets': { type: 'tool' },
  143. 'grenade': {type: 'weapon' },
  144. 'bolas': {type: 'weapon' },
  145. 'laser rifle': {type: 'weapon' },
  146. 'energy cell': {type: 'tool' },
  147. 'bayonet': {type: 'weapon' },
  148. 'charm': {type: 'tool'},
  149. 'medicine': {type: 'tool'}
  150. }, Room.Craftables);
  151. for(var k in carryable) {
  152. var lk = _(k);
  153. var store = carryable[k];
  154. var have = $SM.get('stores["'+k+'"]');
  155. var num = Path.outfit[k];
  156. num = typeof num == 'number' ? num : 0;
  157. if (have < num) { num = have; }
  158. var numAvailable = $SM.get('stores["'+k+'"]', true);
  159. var row = $('div#outfit_row_' + k.replace(' ', '-'), outfit);
  160. if((store.type == 'tool' || store.type == 'weapon') && have > 0) {
  161. total += num * Path.getWeight(k);
  162. if(row.length === 0) {
  163. row = Path.createOutfittingRow(k, num, store.name);
  164. var curPrev = null;
  165. outfit.children().each(function(i) {
  166. var child = $(this);
  167. if(child.attr('id').indexOf('outfit_row_') === 0) {
  168. var cName = child.children('.row_key').text();
  169. if(cName < lk) {
  170. curPrev = child.attr('id');
  171. }
  172. }
  173. });
  174. if(curPrev == null) {
  175. row.insertAfter(wRow);
  176. } else {
  177. row.insertAfter(outfit.find('#' + curPrev));
  178. }
  179. } else {
  180. $('div#' + row.attr('id') + ' > div.row_val > span', outfit).text(num);
  181. $('div#' + row.attr('id') + ' .tooltip .numAvailable', outfit).text(numAvailable - num);
  182. }
  183. if(num === 0) {
  184. $('.dnBtn', row).addClass('disabled');
  185. $('.dnManyBtn', row).addClass('disabled');
  186. } else {
  187. $('.dnBtn', row).removeClass('disabled');
  188. $('.dnManyBtn', row).removeClass('disabled');
  189. }
  190. if(num >= numAvailable || space < Path.getWeight(k)) {
  191. $('.upBtn', row).addClass('disabled');
  192. $('.upManyBtn', row).addClass('disabled');
  193. } else if(space >= Path.getWeight(k)) {
  194. $('.upBtn', row).removeClass('disabled');
  195. $('.upManyBtn', row).removeClass('disabled');
  196. }
  197. } else if(have === 0 && row.length > 0) {
  198. row.remove();
  199. }
  200. }
  201. // Update bagspace
  202. $('#bagspace').text(_('free {0}/{1}', Math.floor(Path.getCapacity() - total) , Path.getCapacity()));
  203. if(Path.outfit['cured meat'] > 0) {
  204. Button.setDisabled($('#embarkButton'), false);
  205. } else {
  206. Button.setDisabled($('#embarkButton'), true);
  207. }
  208. },
  209. createOutfittingRow: function(key, num, name) {
  210. if(!name) name = _(key);
  211. var row = $('<div>').attr('id', 'outfit_row_' + key.replace(' ', '-')).addClass('outfitRow').attr('key',key);
  212. $('<div>').addClass('row_key').text(name).appendTo(row);
  213. var val = $('<div>').addClass('row_val').appendTo(row);
  214. $('<span>').text(num).appendTo(val);
  215. $('<div>').addClass('upBtn').appendTo(val).click([1], Path.increaseSupply);
  216. $('<div>').addClass('dnBtn').appendTo(val).click([1], Path.decreaseSupply);
  217. $('<div>').addClass('upManyBtn').appendTo(val).click([10], Path.increaseSupply);
  218. $('<div>').addClass('dnManyBtn').appendTo(val).click([10], Path.decreaseSupply);
  219. $('<div>').addClass('clear').appendTo(row);
  220. var numAvailable = $SM.get('stores["'+key+'"]', true);
  221. var tt = $('<div>').addClass('tooltip bottom right').appendTo(row);
  222. $('<div>').addClass('row_key').text(_('weight')).appendTo(tt);
  223. $('<div>').addClass('row_val').text(Path.getWeight(key)).appendTo(tt);
  224. $('<div>').addClass('row_key').text(_('available')).appendTo(tt);
  225. $('<div>').addClass('row_val').addClass('numAvailable').text(numAvailable).appendTo(tt);
  226. return row;
  227. },
  228. increaseSupply: function(btn) {
  229. var supply = $(this).closest('.outfitRow').attr('key');
  230. Engine.log('increasing ' + supply + ' by up to ' + btn.data);
  231. var cur = Path.outfit[supply];
  232. cur = typeof cur == 'number' ? cur : 0;
  233. if(Path.getFreeSpace() >= Path.getWeight(supply) && cur < $SM.get('stores["'+supply+'"]', true)) {
  234. var maxExtraByWeight = Math.floor(Path.getFreeSpace() / Path.getWeight(supply));
  235. var maxExtraByStore = $SM.get('stores["'+supply+'"]', true) - cur;
  236. var maxExtraByBtn = btn.data;
  237. Path.outfit[supply] = cur + Math.min(maxExtraByBtn, Math.min(maxExtraByWeight, maxExtraByStore));
  238. $SM.set('outfit['+supply+']', Path.outfit[supply]);
  239. Path.updateOutfitting();
  240. }
  241. },
  242. decreaseSupply: function(btn) {
  243. var supply = $(this).closest('.outfitRow').attr('key');
  244. Engine.log('decreasing ' + supply + ' by up to ' + btn.data);
  245. var cur = Path.outfit[supply];
  246. cur = typeof cur == 'number' ? cur : 0;
  247. if(cur > 0) {
  248. Path.outfit[supply] = Math.max(0, cur - btn.data);
  249. $SM.set('outfit['+supply+']', Path.outfit[supply]);
  250. Path.updateOutfitting();
  251. }
  252. },
  253. onArrival: function(transition_diff) {
  254. Path.setTitle();
  255. Path.updateOutfitting();
  256. Path.updatePerks(true);
  257. $SM.set('outfit', Path.outfit);
  258. Engine.moveStoresView($('#perks'), transition_diff);
  259. },
  260. setTitle: function() {
  261. document.title = _('A Dusty Path');
  262. },
  263. embark: function() {
  264. for(var k in Path.outfit) {
  265. $SM.add('stores["'+k+'"]', -Path.outfit[k]);
  266. }
  267. $SM.remove('outfit');
  268. World.onArrival();
  269. $('#outerSlider').animate({left: '-700px'}, 300);
  270. Engine.activeModule = World;
  271. },
  272. handleStateUpdates: function(e){
  273. if(e.category == 'character' && e.stateName.indexOf('character.perks') === 0 && Engine.activeModule == Path){
  274. Path.updatePerks();
  275. };
  276. },
  277. scrollSidebar: function(direction, reset){
  278. if( typeof reset != "undefined" ){
  279. $('#perks').css('top', '0px');
  280. $('#storesContainer').css('top', '206px');
  281. Path._STORES_OFFSET = 0;
  282. return;
  283. }
  284. var momentum = 10;
  285. if( direction == 'up' )
  286. momentum = momentum * -1
  287. if( direction == 'down' && inView( direction, $('#perks') ) ){
  288. return false;
  289. }else if( direction == 'up' && inView( direction, $('#storesContainer') ) ){
  290. return false;
  291. }
  292. scrollByX( $('#perks'), momentum );
  293. scrollByX( $('#storesContainer'), momentum );
  294. Path._STORES_OFFSET += momentum;
  295. }
  296. };