@@ -23,6 +23,13 @@ import {
23
23
} from '@darkthrone/game-data' ;
24
24
import { getRandomNumber } from '../utils' ;
25
25
import { Paginator } from '../lib/paginator' ;
26
+ import {
27
+ getAttackModifier ,
28
+ getDefenseModifier ,
29
+ getIncomeModifier ,
30
+ getCostModifier ,
31
+ applyBonuses ,
32
+ } from '../lib/bonusHelper' ;
26
33
27
34
export default class PlayerModel {
28
35
private ctx : Context ;
@@ -44,14 +51,20 @@ export default class PlayerModel {
44
51
fortification : number ;
45
52
housing : number ;
46
53
} ;
54
+ public proficiencyPoints : {
55
+ strength : number ;
56
+ constitution : number ;
57
+ wealth : number ;
58
+ dexterity : number ;
59
+ charisma : number ;
60
+ } ;
47
61
48
62
public units : PlayerUnitsModel [ ] ;
49
63
50
64
constructor ( ctx : Context , data : PlayerRow , units : PlayerUnitsModel [ ] ) {
51
65
this . ctx = ctx ;
52
-
53
- this . populateFromRow ( data ) ;
54
66
this . units = units ;
67
+ this . populateFromRow ( data ) ;
55
68
}
56
69
57
70
async serialise ( ) : Promise < PlayerObject | AuthedPlayerObject > {
@@ -74,14 +87,14 @@ export default class PlayerModel {
74
87
if ( ! isAuthed ) return playerObject ;
75
88
76
89
const attackStrength = await this . calculateAttackStrength ( ) ;
77
- const defenceStrength = await this . calculateDefenceStrength ( ) ;
90
+ const defenseStrength = await this . calculateDefenseStrength ( ) ;
78
91
79
92
const date24HoursAgo = new Date ( Date . now ( ) - 24 * 60 * 60 * 1000 ) ;
80
93
const depositHistory = await this . fetchBankHistory ( date24HoursAgo ) ;
81
94
82
95
const authedPlayerObject : AuthedPlayerObject = Object . assign ( playerObject , {
83
96
attackStrength : attackStrength ,
84
- defenceStrength : defenceStrength ,
97
+ defenseStrength : defenseStrength ,
85
98
attackTurns : this . attackTurns ,
86
99
experience : this . experience ,
87
100
goldInBank : this . goldInBank ,
@@ -96,6 +109,8 @@ export default class PlayerModel {
96
109
quantity : unit . quantity ,
97
110
} ) ) ,
98
111
structureUpgrades : this . structureUpgrades ,
112
+ proficiencyPoints : this . proficiencyPoints ,
113
+ remainingProficiencyPoints : this . proficiencyPointsRemaining ,
99
114
} ) ;
100
115
101
116
return authedPlayerObject ;
@@ -151,13 +166,50 @@ export default class PlayerModel {
151
166
return fortificationUpgrades [ this . structureUpgrades . fortification ] ;
152
167
}
153
168
169
+ get proficiencyPointsTotal ( ) : number {
170
+ return Object . values ( this . proficiencyPoints ) . reduce (
171
+ ( acc , points ) => acc + points ,
172
+ 0 ,
173
+ ) ;
174
+ }
175
+
176
+ get proficiencyPointsRemaining ( ) : number {
177
+ // The player gets 1 proficiency point per level
178
+ // Since the player starts at level 1, we subtract 1 from the level
179
+ return this . level - 1 - this . proficiencyPointsTotal ;
180
+ }
181
+
182
+ async upgradeProficiencyPoints ( points : {
183
+ strength : number ;
184
+ constitution : number ;
185
+ wealth : number ;
186
+ dexterity : number ;
187
+ charisma : number ;
188
+ } ) {
189
+ this . ctx . logger . debug ( { points } , 'Upgrading proficiency points' ) ;
190
+ const totalPoints = Object . values ( points ) . reduce (
191
+ ( acc , point ) => acc + point ,
192
+ 0 ,
193
+ ) ;
194
+
195
+ if ( totalPoints > this . proficiencyPointsRemaining ) {
196
+ throw new Error ( 'Not enough proficiency points' ) ;
197
+ }
198
+
199
+ this . proficiencyPoints = points ;
200
+ console . log ( 'this.proficiencyPoints' , this . proficiencyPoints ) ;
201
+ await this . save ( ) ;
202
+ console . log ( 'this.proficiencyPoints' , this . proficiencyPoints ) ;
203
+ }
204
+
154
205
async upgradeStructure (
155
206
type : keyof typeof structureUpgrades ,
156
207
desiredUpgrade : StructureUpgrade ,
157
208
) {
158
209
this . ctx . logger . debug ( { type } , 'Upgrading structure' ) ;
159
-
160
- this . gold -= desiredUpgrade . cost ;
210
+ const bonus = getCostModifier ( this ) ;
211
+ const cost = applyBonuses ( false , desiredUpgrade . cost , bonus ) ;
212
+ this . gold -= Math . floor ( cost ) ;
161
213
this . structureUpgrades [ type ] += 1 ;
162
214
163
215
this . save ( ) ;
@@ -168,47 +220,29 @@ export default class PlayerModel {
168
220
( acc , unit ) => acc + unit . calculateAttackStrength ( ) ,
169
221
0 ,
170
222
) ;
171
- if ( this . race === 'human' || this . race === 'undead' ) {
172
- // Humans and Undead get a 5% bonus to attack strength
173
- offense *= 1.05 ;
174
- }
175
- if ( this . class === 'fighter' ) {
176
- // Fighters get a 5% bonus to attack strength
177
- offense *= 1.05 ;
178
- }
223
+ const bonus = getAttackModifier ( this ) ;
224
+ offense = applyBonuses ( true , offense , bonus ) ;
179
225
return Math . floor ( offense ) ;
180
226
}
181
227
182
- async calculateDefenceStrength ( ) : Promise < number > {
183
- let defence = this . units . reduce (
184
- ( acc , unit ) => acc + unit . calculateDefenceStrength ( ) ,
228
+ async calculateDefenseStrength ( ) : Promise < number > {
229
+ let defense = this . units . reduce (
230
+ ( acc , unit ) => acc + unit . calculateDefenseStrength ( ) ,
185
231
0 ,
186
232
) ;
187
- if ( this . race === 'elf' || this . race === 'goblin' ) {
188
- // Elves and Goblins get a 5% bonus to defence strength
189
- defence *= 1.05 ;
190
- }
191
- if ( this . class === 'cleric' ) {
192
- // Clerics get a 5% bonus to defence strength
193
- defence *= 1.05 ;
194
- }
195
-
196
- const fortificationBonus = this . fortification . defenceBonusPercentage ;
197
- defence *= 1 + fortificationBonus / 100 ;
198
-
199
- return Math . floor ( defence ) ;
233
+ const bonus = getDefenseModifier ( this ) ;
234
+ defense = applyBonuses ( true , defense , bonus ) ;
235
+ return Math . floor ( defense ) ;
200
236
}
201
237
202
238
async calculateGoldPerTurn ( ) : Promise < number > {
203
239
let goldPerTurn = this . units . reduce (
204
240
( acc , unit ) => acc + unit . calculateGoldPerTurn ( ) ,
205
241
0 ,
206
242
) ;
207
- if ( this . class === 'thief' ) {
208
- // Thieves get a 5% bonus to gold per turn
209
- goldPerTurn *= 1.05 ;
210
- }
211
243
244
+ const bonus = getIncomeModifier ( this ) ;
245
+ goldPerTurn = applyBonuses ( true , goldPerTurn , bonus ) ;
212
246
const fortificationGoldPerTurn = this . fortification . goldPerTurn ;
213
247
goldPerTurn += fortificationGoldPerTurn ;
214
248
@@ -233,12 +267,12 @@ export default class PlayerModel {
233
267
const warHistoryID = `WRH-${ ulid ( ) } ` ;
234
268
235
269
const playerAttackStrength = await this . calculateAttackStrength ( ) ;
236
- const targetPlayerDefenceStrength =
237
- await targetPlayer . calculateDefenceStrength ( ) ;
270
+ const targetPlayerDefenseStrength =
271
+ await targetPlayer . calculateDefenseStrength ( ) ;
238
272
239
273
const isVictor = this . determineIsVictor (
240
274
playerAttackStrength ,
241
- targetPlayerDefenceStrength ,
275
+ targetPlayerDefenseStrength ,
242
276
) ;
243
277
244
278
// Calculate XP
@@ -259,7 +293,7 @@ export default class PlayerModel {
259
293
attack_turns_used : attackTurns ,
260
294
is_attacker_victor : false ,
261
295
attacker_strength : playerAttackStrength ,
262
- defender_strength : targetPlayerDefenceStrength ,
296
+ defender_strength : targetPlayerDefenseStrength ,
263
297
gold_stolen : 0 ,
264
298
created_at : new Date ( ) ,
265
299
attacker_experience : 0 ,
@@ -291,7 +325,7 @@ export default class PlayerModel {
291
325
attack_turns_used : attackTurns ,
292
326
is_attacker_victor : true ,
293
327
attacker_strength : playerAttackStrength ,
294
- defender_strength : targetPlayerDefenceStrength ,
328
+ defender_strength : targetPlayerDefenseStrength ,
295
329
gold_stolen : winnings ,
296
330
created_at : new Date ( ) ,
297
331
attacker_experience : victorExperience ,
@@ -311,6 +345,7 @@ export default class PlayerModel {
311
345
experience : this . experience ,
312
346
overall_rank : this . overallRank ,
313
347
structureUpgrades : this . structureUpgrades ,
348
+ proficiencyPoints : this . proficiencyPoints ,
314
349
} ,
315
350
) ;
316
351
@@ -335,6 +370,13 @@ export default class PlayerModel {
335
370
fortification : row . structureUpgrades ?. fortification || 0 ,
336
371
housing : row . structureUpgrades ?. housing || 0 ,
337
372
} ;
373
+ this . proficiencyPoints = {
374
+ strength : row . proficiencyPoints ?. strength || 0 ,
375
+ constitution : row . proficiencyPoints ?. constitution || 0 ,
376
+ wealth : row . proficiencyPoints ?. wealth || 0 ,
377
+ dexterity : row . proficiencyPoints ?. dexterity || 0 ,
378
+ charisma : row . proficiencyPoints ?. charisma || 0 ,
379
+ } ;
338
380
}
339
381
340
382
static async fetchAllForUser ( ctx : Context , user : UserModel ) {
0 commit comments