Completed
Push — master ( 1c6c4e...f7d036 )
by Andres
29s
created

src/scripts/component/exotic.js   B

Complexity

Total Complexity 36
Complexity/F 2.4

Size

Lines of Code 194
Function Count 15

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 0
wmc 36
c 3
b 0
f 0
nc 16
mnd 2
bc 34
fnc 15
dl 0
loc 194
rs 8.8
bpm 2.2666
cpm 2.4
noi 0

1 Function

Rating   Name   Duplication   Size   Complexity  
B angular.controller(ꞌct_exoticꞌ) 0 184 1
1
/**
2
 exotic
3
 Component that handles the exotic matter and prestige logic.
4
 It includes exotic matter production, exotic upgrades, and infusion of
5
 subatomic particles to boost exotic production.
6
 A prestige erases the progress of a single element, and produces exotic
7
 matter for said element.
8
9
 @namespace Components
10
 */
11
'use strict';
12
13
angular.module('game').component('exotic', {
14
  templateUrl: 'views/exotic.html',
15
  controller:  'ct_exotic',
16
  controllerAs: 'ct'
17
});
18
19
angular.module('game').controller('ct_exotic', ['state', 'format', 'visibility', 'upgrade', 'data', 'util',
20
  function (state, format, visibility, upgrade, data, util) {
21
    let ct = this;
22
    ct.state = state;
23
    ct.data = data;
24
    ct.util = util;
25
    ct.format = format;
26
    ct.infuse = {};
27
28
    function update(player){
29
      for(let key in player.cooldowns){
30
        if(player.cooldowns[key] > 0){
31
          player.cooldowns[key]--;
32
        }
33
      }
34
    }
35
36
    /* Exotic production is a function of the different resources of each
37
    element. Additionally, multi-element molecules count double, once for
38
    each participating element. */
39
    ct.exoticProduction = function(element) {
40
      let production = {};
41
      let exoticResource = data.elements[element].exotic;
42
      production[exoticResource] = 0;
43
      for (let resource of data.elements[element].includes) {
44
        if (!state.player.resources[resource].unlocked) {
45
          continue;
46
        }
47
        for (let elem in data.resources[resource].elements) {
48
          let numberAtoms = data.resources[resource].elements[elem];
49
          let prod = prestigeFormula(state.player.resources[resource].number*numberAtoms);
50
51
          let args = {
52
            production: prod,
53
            resource: resource
54
          }
55
56
          upgrade.executeAll(data.exotic_upgrades, state.player.exotic_upgrades[elem], ['production', 'exotic'], args);
57
58
          // extract back the value from applying the upgrades
59
          let newExotic = data.elements[elem].exotic;
60
          production[newExotic] = (production[newExotic] || 0) + args.production;
61
        }
62
      }
63
      for (let key in production) {
64
        // we adjust the infusion
65
        production[key] = Math.floor(production[key]*ct.totalInfuseBoost());
66
      }
67
68
      return production;
69
    };
70
71
    function prestigeFormula(resource){
72
      let sum = 0;
73
      let i = 0;
74
      while(i < data.exotic_ranges.length && resource > data.exotic_ranges[i].top){
75
        sum += data.exotic_ranges[i].max_value;
76
        i++;
77
      }
78
      if(i < data.exotic_ranges.length){
79
        let L = data.exotic_ranges[i].max_value;
80
        let k = 12/data.exotic_ranges[i].range;
81
        let x0 = data.exotic_ranges[i].midpoint;
82
        let sigmoid = Math.pow(Math.E, -k*(resource-x0));
83
84
        sum += L/(1+sigmoid);
85
      }
86
      return Math.floor(sum);
87
    }
88
89
    ct.exoticPrestige = function(index) {
90
      let slot = state.player.element_slots[index];
91
      let resources = state.player.resources;
92
      let cooldown = state.player.cooldowns[index];
93
      let production = 0;
94
      if(cooldown === 0){
95
        production = ct.exoticProduction(slot.element);
96
      }
97
98
      for (let key in production) {
99
        resources[key].number += production[key];
100
        resources[key].unlocked = true;
101
      }
102
103
      for(let resource in ct.infuse){
104
        state.player.resources[resource].number -= ct.infuse[resource];
105
      }
106
107
      upgrade.resetElement(state.player, slot.element);
108
109
      // we deactivate reactions and redoxes
110
      for (let reaction of slot.reactions) {
111
        reaction.active = false;
112
      }
113
114
      for (let redox of slot.redoxes) {
115
        redox.active = false;
116
      }
117
118
      // we cache them in case players want to pick up the same element
119
      // the cache only lasts the current session
120
      state.reactionsCache[slot.element] = slot.reactions;
121
      state.redoxesCache[slot.element] = slot.redoxes;
122
123
      state.player.element_slots[index] = null;
124
125
      if(cooldown === 0){
126
        state.player.cooldowns[index] = 60*60;
127
      }
128
    };
129
130
    ct.buyExoticUpgrade = function(name, slot) {
131
      let price = data.exotic_upgrades[name].price;
132
      let currency = data.elements[slot.element].exotic;
133
      upgrade.buyUpgrade(state.player,
134
        state.player.exotic_upgrades[slot.element],
135
        data.exotic_upgrades[name],
136
        name,
137
        price,
138
        currency);
139
    };
140
141
    ct.setPercentage = function(resource, percentage) {
142
      ct.infuse[resource] = Math.floor(state.player.resources[resource].number*(percentage/100));
143
    };
144
145
    ct.fixNumber = function(resource) {
146
      ct.infuse[resource] = Math.max(0, Math.min(state.player.resources[resource].number, ct.infuse[resource]));
147
    };
148
149
    /* This function checks that values inserted in the text boxes are
150
    valid numbers */
151
    ct.isValidInfusion = function() {
152
      let valid = true;
153
      for(let resource in ct.infuse){
154
        valid = valid && Number.isFinite(ct.infuse[resource]);
155
      }
156
      return valid;
157
    };
158
159
    ct.infuseBoost = function(resource) {
160
        let number = Math.min(ct.infuse[resource], state.player.resources[resource].number);
161
        if(number === 0){
162
          return 1;
163
        }
164
        // log adds diminishing returns to the infusion
165
        return 1 + Math.log(number)/Math.log(1.25)*ct.data.constants.INFUSE_POWER;
166
    };
167
168
    /* The infusion boosts are multiplicative with respect to each other */
169
    ct.totalInfuseBoost = function() {
170
      let total = 1;
171
      for(let resource in ct.infuse){
172
        total *= ct.infuseBoost(resource);
173
      }
174
      return total;
175
    };
176
177
    ct.visibleExoticUpgrades = function(slot) {
178
      return visibility.visible(data.exotic_upgrades, isExoticUpgradeVisible, slot);
179
    };
180
181
    function isExoticUpgradeVisible(name, slot) {
182
      return visibility.isUpgradeVisible(name, slot, data.exotic_upgrades[name]);
183
    }
184
185
    ct.visibleSubatomic = function() {
186
      return visibility.visible(data.resources, isSubatomicVisible, '');
187
    };
188
189
    function isSubatomicVisible(name) {
190
      if (!state.player.resources[name].unlocked) {
191
        return false;
192
      }
193
194
      if(data.resources[name].type &&
195
         data.resources[name].type.indexOf('subatomic') !== -1){
196
          return true;
197
      }
198
199
      return false;
200
    }
201
202
    state.registerUpdate('exotic', update);
203
  }
204
]);
205