OSDN Git Service

水上戦闘機の制空ボーナスを実装(未検証分
[kcd/KCD.git] / KCD / HMKCShipObject+Extensions.m
1 //
2 //  HMKCShipObject+Extensions.m
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2014/06/08.
6 //  Copyright (c) 2014年 Hori,Masaki. All rights reserved.
7 //
8
9 #import "HMKCShipObject+Extensions.h"
10 #import "HMKCMasterShipObject.h"
11 #import "HMKCMasterSType.h"
12
13 #import "HMKCMasterSlotItemObject.h"
14 #import "HMKCSlotItemObject+Extensions.h"
15
16 #import "HMServerDataStore.h"
17 #import "HMTemporaryDataStore.h"
18 #import "HMUserDefaults.h"
19
20
21 static NSArray *shortSTypeNames = nil;
22 static NSArray *levelUpExps = nil;
23
24 @implementation HMKCShipObject (Extensions)
25
26 + (void)load
27 {
28         static dispatch_once_t onceToken;
29         dispatch_once(&onceToken, ^{
30                 NSBundle *mainBundle = [NSBundle mainBundle];
31                 NSURL *url = [mainBundle URLForResource:@"STypeShortName" withExtension:@"plist"];
32                 NSArray *array = [[NSArray alloc] initWithContentsOfURL:url];
33                 if(!array) {
34                         NSLog(@"Can not load STypeShortName.plist.");
35                 }
36                 shortSTypeNames = [array copy];
37                 
38                 url = [mainBundle URLForResource:@"LevelUpExp" withExtension:@"plist"];
39                 array = [[NSArray alloc] initWithContentsOfURL:url];
40                 if(!array) {
41                         NSLog(@"Can not load LevelUpExp.plist.");
42                 }
43                 levelUpExps = [array copy];
44         });
45 }
46
47
48 + (NSSet *)keyPathsForValuesAffectingIsMaxKaryoku
49 {
50         return [NSSet setWithObjects:@"karyoku_1", @"kyouka_0", nil];
51 }
52 - (NSNumber *)isMaxKaryoku
53 {
54         [self willAccessValueForKey:@"master_ship"];
55         [self willAccessValueForKey:@"karyoku_1"];
56         [self willAccessValueForKey:@"kyouka_0"];
57         NSInteger defaultValue = [self.master_ship.houg_0 integerValue];
58         NSInteger maxValue = [self.karyoku_1 integerValue];
59         NSInteger growth = [self.kyouka_0 integerValue];
60         [self didAccessValueForKey:@"kyouka_0"];
61         [self didAccessValueForKey:@"karyoku_1"];
62         [self didAccessValueForKey:@"master_ship"];
63         
64         return @(defaultValue + growth >= maxValue);
65 }
66
67 + (NSSet *)keyPathsForValuesAffectingIsMaxRaisou
68 {
69         return [NSSet setWithObjects:@"raisou_1", @"kyouka_1", nil];
70 }
71 - (NSNumber *)isMaxRaisou
72 {
73         [self willAccessValueForKey:@"master_ship"];
74         [self willAccessValueForKey:@"raisou_1"];
75         [self willAccessValueForKey:@"kyouka_1"];
76         NSInteger defaultValue = [self.master_ship.raig_0 integerValue];
77         NSInteger maxValue = [self.raisou_1 integerValue];
78         NSInteger growth = [self.kyouka_1 integerValue];
79         [self didAccessValueForKey:@"kyouka_1"];
80         [self didAccessValueForKey:@"raisou_1"];
81         [self didAccessValueForKey:@"master_ship"];
82         
83         return @(defaultValue + growth >= maxValue);
84 }
85
86 + (NSSet *)keyPathsForValuesAffectingIsMaxTaiku
87 {
88         return [NSSet setWithObjects:@"taiku_1", @"kyouka_2", nil];
89 }
90 - (NSNumber *)isMaxTaiku
91 {
92         [self willAccessValueForKey:@"master_ship"];
93         [self willAccessValueForKey:@"taiku_1"];
94         [self willAccessValueForKey:@"kyouka_2"];
95         NSInteger defaultValue = [self.master_ship.tyku_0 integerValue];
96         NSInteger maxValue = [self.taiku_1 integerValue];
97         NSInteger growth = [self.kyouka_2 integerValue];
98         [self didAccessValueForKey:@"kyouka_2"];
99         [self didAccessValueForKey:@"taiku_1"];
100         [self didAccessValueForKey:@"master_ship"];
101         
102         return @(defaultValue + growth >= maxValue);
103 }
104
105 + (NSSet *)keyPathsForValuesAffectingIsMaxSoukou
106 {
107         return [NSSet setWithObjects:@"soukou_1", @"kyouka_3", nil];
108 }
109 - (NSNumber *)isMaxSoukou
110 {
111         [self willAccessValueForKey:@"master_ship"];
112         [self willAccessValueForKey:@"soukou_1"];
113         [self willAccessValueForKey:@"kyouka_3"];
114         NSInteger defaultValue = [self.master_ship.souk_0 integerValue];
115         NSInteger maxValue = [self.soukou_1 integerValue];
116         NSInteger growth = [self.kyouka_3 integerValue];
117         [self didAccessValueForKey:@"kyouka_3"];
118         [self didAccessValueForKey:@"soukou_1"];
119         [self didAccessValueForKey:@"master_ship"];
120         
121         return @(defaultValue + growth >= maxValue);
122 }
123
124 + (NSSet *)keyPathsForValuesAffectingIsMaxLucky
125 {
126         return [NSSet setWithObjects:@"lucky_1", @"kyouka_4", nil];
127 }
128 - (NSNumber *)isMaxLucky
129 {
130         [self willAccessValueForKey:@"master_ship"];
131         [self willAccessValueForKey:@"lucky_1"];
132         [self willAccessValueForKey:@"kyouka_4"];
133         NSInteger defaultValue = [self.master_ship.luck_0 integerValue];
134         NSInteger maxValue = [self.lucky_1 integerValue];
135         NSInteger growth = [self.kyouka_4 integerValue];
136         [self didAccessValueForKey:@"kyouka_4"];
137         [self didAccessValueForKey:@"lucky_1"];
138         [self didAccessValueForKey:@"master_ship"];
139         
140         return @(defaultValue + growth >= maxValue);
141 }
142
143 + (NSSet *)keyPathsForValuesAffectingName
144 {
145         return [NSSet setWithObjects:@"ship_id", nil];
146 }
147 - (NSString *)name
148 {
149         return [self.master_ship valueForKey:@"name"];
150 }
151
152 + (NSSet *)keyPathsForValuesAffectingShortTypeName
153 {
154         return [NSSet setWithObjects:@"ship_id", nil];
155 }
156 - (NSString *)shortTypeName
157 {
158         [self willAccessValueForKey:@"master_ship"];
159         NSNumber *idValue = self.master_ship.stype.id;
160         [self didAccessValueForKey:@"master_ship"];
161         if(!idValue || [idValue isKindOfClass:[NSNull class]]) return nil;
162         
163         if([shortSTypeNames count] < [idValue integerValue]) return nil;
164         
165         return shortSTypeNames[[idValue integerValue] - 1];
166 }
167
168 + (NSSet *)keyPathsForValuesAffectingNext
169 {
170         return [NSSet setWithObjects:@"exp", nil];
171 }
172 - (NSNumber *)next
173 {
174         [self willAccessValueForKey:@"lv"];
175         id lvValue = self.lv;
176         [self didAccessValueForKey:@"lv"];
177         [self willAccessValueForKey:@"exp"];
178         id expValue = self.exp;
179         [self didAccessValueForKey:@"exp"];
180         
181         NSUInteger currentLevel = [lvValue integerValue];
182         if(currentLevel >= [levelUpExps count]) {
183                 return nil;
184         }
185         if(currentLevel == 99) return nil;
186         
187         NSUInteger nextExp = [[levelUpExps objectAtIndex:currentLevel] integerValue];
188         if(currentLevel > 99) {
189                 nextExp += 1000000;
190         }
191         return @(nextExp - [expValue integerValue]);
192 }
193
194 + (NSSet *)keyPathsForValuesAffectingStatus
195 {
196         return [NSSet setWithObjects:@"nowhp", @"maxph", nil];
197 }
198 - (NSInteger)status
199 {
200         [self willAccessValueForKey:@"maxhp"];
201         [self willAccessValueForKey:@"nowhp"];
202         NSInteger maxhp = [self.maxhp integerValue];
203         CGFloat nowhp = [self.nowhp integerValue];
204         [self didAccessValueForKey:@"nowhp"];
205         [self didAccessValueForKey:@"maxhp"];
206         
207         CGFloat status = nowhp / maxhp;
208         if(status <= 0.25) {
209                 return 3;
210         }
211         if(status <= 0.5) {
212                 return 2;
213         }
214         if(status <= 0.75) {
215                 return 1;
216                 
217         }
218         return 0;
219 }
220
221 + (NSSet *)keyPathsForValuesAffectingStatusColor
222 {
223         return [NSSet setWithObjects:@"status", nil];
224 }
225 - (NSColor *)statusColor
226 {
227         [self willAccessValueForKey:@"maxhp"];
228         [self willAccessValueForKey:@"nowhp"];
229         NSInteger maxhp = [self.maxhp integerValue];
230         CGFloat nowhp = [self.nowhp integerValue];
231         [self didAccessValueForKey:@"nowhp"];
232         [self didAccessValueForKey:@"maxhp"];
233         
234         CGFloat status = nowhp / maxhp;
235         if(status <= 0.25) {
236                 return [NSColor redColor];
237         }
238         if(status <= 0.5) {
239                 return [NSColor orangeColor];
240         }
241         if(status <= 0.75) {
242                 return [NSColor yellowColor];
243                 
244         }
245         return [NSColor controlTextColor];
246 }
247
248 + (NSSet *)keyPathsForValuesAffectingConditionColor
249 {
250         return [NSSet setWithObjects:@"cond", nil];
251 }
252 - (NSColor *)conditionColor
253 {
254         return [NSColor controlTextColor];
255 }
256
257 - (NSColor *)planColor
258 {
259         if(!HMStandardDefaults.showsPlanColor) return [NSColor controlTextColor];
260         
261         [self willAccessValueForKey:@"sally_area"];
262         NSInteger planType = [self.sally_area integerValue];
263         [self didAccessValueForKey:@"sally_area"];
264         if(planType == 1) return HMStandardDefaults.plan01Color;
265         if(planType == 2) return HMStandardDefaults.plan02Color;
266         if(planType == 3) return HMStandardDefaults.plan03Color;
267         if(planType == 4) return HMStandardDefaults.plan04Color;
268         if(planType == 5) return HMStandardDefaults.plan05Color;
269         if(planType == 6) return HMStandardDefaults.plan06Color;
270         return [NSColor controlTextColor];
271 }
272
273
274 - (NSNumber *)maxFuel
275 {
276         [self willAccessValueForKey:@"master_ship"];
277         NSNumber *number = self.master_ship.fuel_max;
278         [self didAccessValueForKey:@"master_ship"];
279         return number;
280 }
281 - (NSNumber *)maxBull
282 {
283         [self willAccessValueForKey:@"master_ship"];
284         NSNumber *number = self.master_ship.bull_max;
285         [self didAccessValueForKey:@"master_ship"];
286         return number;
287 }
288
289 - (NSNumber *)upgradeLevel
290 {
291         [self willAccessValueForKey:@"master_ship"];
292         NSNumber *number = self.master_ship.afterlv;
293         [self didAccessValueForKey:@"master_ship"];
294         return number;
295 }
296 + (NSSet *)keyPathsForValuesAffectingUpgradeExp
297 {
298         return [NSSet setWithObjects:@"exp", nil];
299 }
300 - (NSNumber *)upgradeExp
301 {
302         NSInteger upgradeLevtl = [self.upgradeLevel integerValue];
303         if(upgradeLevtl <= 0) return nil;
304         
305         NSInteger upgradeExp = [[levelUpExps objectAtIndex:upgradeLevtl - 1] integerValue];
306         NSInteger exp = [self.exp integerValue];
307         upgradeExp -= exp;
308         if(upgradeExp < 0) {
309                 upgradeExp = 0;
310         }
311         return @(upgradeExp);
312 }
313
314 - (NSNumber *)totalEquipment
315 {
316         NSInteger total = 0;
317         [self willAccessValueForKey:@"master_ship"];
318         total += self.master_ship.maxeq_0.integerValue;
319         total += self.master_ship.maxeq_1.integerValue;
320         total += self.master_ship.maxeq_2.integerValue;
321         total += self.master_ship.maxeq_3.integerValue;
322         total += self.master_ship.maxeq_4.integerValue;
323         [self didAccessValueForKey:@"master_ship"];
324         return @(total);
325 }
326
327 + (NSSet *)keyPathsForValuesAffectingSeiku
328 {
329         return [NSSet setWithObjects:
330                         @"slot_0", @"slot_1", @"slot_2", @"slot_3", @"slot_4",
331                         @"onslot_0", @"onslot_1", @"onslot_2", @"onslot_3", @"onslot_4",
332                         nil];
333 }
334
335 - (HMKCSlotItemObject *)slotItemAtIndex:(NSUInteger)index
336 {
337         HMServerDataStore *store = [HMServerDataStore defaultManager];
338
339         NSString *key = [NSString stringWithFormat:@"slot_%ld", index];
340         NSNumber *itemId = [self valueForKey:key];
341         if(itemId.integerValue == -1) return nil;
342         NSError *error = nil;
343         NSArray *array = [store objectsWithEntityName:@"SlotItem"
344                                                                                         error:&error
345                                                                   predicateFormat:@"id = %@", itemId];
346         if(array.count == 0) return nil;
347         HMKCSlotItemObject *slotItem = array[0];
348         return slotItem;
349 }
350 - (NSNumber *)seiku
351 {
352         NSArray *effectiveTypes = @[@6, @7, @8, @11];
353         __block NSInteger totalSeiku = 0;
354         for(NSInteger i = 0; i < 5; i++) {
355                 HMKCSlotItemObject *slotItem = [self slotItemAtIndex:i];
356                 HMKCMasterSlotItemObject *master = slotItem.master_slotItem;
357                 NSNumber *type2 = master.type_2;
358                 if(![effectiveTypes containsObject:type2]) {
359                         continue;
360                 }
361                 
362                 NSString *key = [NSString stringWithFormat:@"onslot_%ld", i];
363                 NSNumber *itemCountValue = [self valueForKey:key];
364                 NSNumber *taikuValue = master.tyku;
365                 NSInteger itemCount = [itemCountValue integerValue];
366                 NSInteger taiku = [taikuValue integerValue];
367                 if(itemCount && taiku) {
368                         totalSeiku += floor(taiku * sqrt(itemCount));
369                 }
370         }
371         
372         return @(totalSeiku);
373 }
374 - (NSNumber *)extraSeiku
375 {
376         NSArray *fighterTypes = @[@6];
377         NSArray *bomberTypes = @[@7];
378         NSArray *attackerTypes = @[@8];
379         NSArray *floatplaneBomberTypes = @[@11];
380         NSArray *floatplaneFighterTypes = @[@45];
381         
382         NSInteger fighterBonus[] = {0, 0, 2, 5, 9, 14, 14, 22};
383         NSInteger bomberBonus[] = {0, 0, 0, 0, 0, 0, 0, 0};
384         NSInteger attackerBonus[] = {0, 0, 0, 0, 0, 0, 0, 0};
385         NSInteger floatplaneBomberBonus[] = {0, 0, 1, 1, 1, 3, 3, 6};
386         NSInteger floatplaneFighterBonus[] = {0, 0, 0, 0, 0, 0, 0, 0};
387         NSInteger bonus[] = {0, 1, 1, 2, 2, 2, 2, 3};
388         
389         NSInteger extraSeiku = 0;
390         for(NSInteger i = 0; i < 5; i++) {
391                 NSString *key = [NSString stringWithFormat:@"onslot_%ld", i];
392                 NSNumber *itemCountValue = [self valueForKey:key];
393                 NSInteger itemCount = [itemCountValue integerValue];
394                 if(itemCount == 0) continue;
395                 
396                 HMKCSlotItemObject *slotItem = [self slotItemAtIndex:i];
397                 NSInteger airLevel = slotItem.alv.integerValue;
398                 
399                 NSInteger *typeBonus = NULL;
400                 
401                 HMKCMasterSlotItemObject *master = slotItem.master_slotItem;
402                 NSNumber *type2 = master.type_2;
403                 if([fighterTypes containsObject:type2]) {
404                         typeBonus = fighterBonus;
405                 }
406                 if([bomberTypes containsObject:type2]) {
407                         typeBonus = bomberBonus;
408                 }
409                 if([attackerTypes containsObject:type2]) {
410                         typeBonus = attackerBonus;
411                 }
412                 if([floatplaneBomberTypes containsObject:type2]) {
413                         typeBonus = floatplaneBomberBonus;
414                 }
415                 if([floatplaneFighterTypes containsObject:type2]) {
416                         typeBonus = floatplaneFighterBonus;
417                 }
418                 if(!typeBonus) continue;
419                 
420                 extraSeiku += typeBonus[airLevel] + bonus[airLevel];
421         }
422         
423         return @(extraSeiku);
424 }
425
426 + (NSSet *)keyPathsForValuesAffectingTotalDrums
427 {
428         return [NSSet setWithObjects:
429                         @"slot_0", @"slot_1", @"slot_2", @"slot_3", @"slot_4",
430                         nil];
431 }
432
433 - (NSNumber *)totalDrums
434 {
435         NSInteger totalBuckets = 0;
436         for(NSInteger i = 0; i < 5; i++) {
437                 HMKCSlotItemObject *slotItem = [self slotItemAtIndex:i];
438                 NSNumber *masterID = slotItem.slotitem_id;
439                 if([masterID isEqualToNumber:@(75)]) {
440                         totalBuckets++;
441                 }
442         }
443         
444         return @(totalBuckets);
445 }
446
447 - (NSNumber *)guardEscaped
448 {
449         HMTemporaryDataStore *store = [HMTemporaryDataStore defaultManager];
450         NSError *error = nil;
451         NSArray *array = [store objectsWithEntityName:@"GuardEscaped"
452                                                                                         error:&error
453                                                                   predicateFormat:@"shipID = %@ AND ensured = TRUE", self.id];
454         if(error) {
455                 NSLog(@"GuardEscaped is invalid. error -> %@", error);
456                 return @NO;
457         }
458         if(!array) return @NO;
459         
460         return array.count == 0 ? @NO : @YES;
461 }
462
463 + (NSSet *)keyPathsForValuesAffectingSteelRequiredInRepair
464 {
465         return [NSSet setWithObject:@"nowhp"];
466 }
467 - (NSNumber *)steelRequiredInRepair
468 {
469         NSInteger steel = self.master_ship.fuel_max.integerValue * 0.06 * (self.maxhp.integerValue - self.nowhp.integerValue);
470         return @(steel);
471 }
472
473 + (NSSet *)keyPathsForValuesAffectingFuelRequiredInRepair
474 {
475         return [NSSet setWithObject:@"nowhp"];
476 }
477 - (NSNumber *)fuelRequiredInRepair
478 {
479         NSInteger fuel = self.master_ship.fuel_max.integerValue * 0.032 * (self.maxhp.integerValue - self.nowhp.integerValue);
480         return @(fuel);
481 }
482
483 @end