OSDN Git Service

カラーセットを使用するように
[kcd/KCD.git] / KCD / Ship.swift
1 //
2 //  [
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2017/01/29.
6 //  Copyright © 2017年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10
11 // swiftlint:disable identifier_name
12 final class Ship: KCManagedObject {
13     
14     @NSManaged dynamic var bull: Int
15     @NSManaged dynamic var cond: Int
16     @NSManaged dynamic var exp: Int
17     @NSManaged dynamic var fleet: NSNumber?
18     @NSManaged dynamic var fuel: Int
19     @NSManaged dynamic var id: Int
20     @NSManaged dynamic var kaihi_0: Int
21     @NSManaged dynamic var kaihi_1: NSNumber?
22     @NSManaged dynamic var karyoku_0: Int
23     @NSManaged dynamic var karyoku_1: Int
24     @NSManaged dynamic var kyouka_0: Int
25     @NSManaged dynamic var kyouka_1: Int
26     @NSManaged dynamic var kyouka_2: Int
27     @NSManaged dynamic var kyouka_3: Int
28     @NSManaged dynamic var kyouka_4: Int
29     @NSManaged dynamic var locked: Int
30     @NSManaged dynamic var locked_equip: NSNumber?
31     @NSManaged dynamic var lucky_0: Int
32     @NSManaged dynamic var lucky_1: Int
33     @NSManaged dynamic var lv: Int
34     @NSManaged dynamic var maxhp: Int
35     @NSManaged dynamic var ndock_time: NSNumber?
36     @NSManaged dynamic var nowhp: Int
37     @NSManaged dynamic var onslot_0: Int
38     @NSManaged dynamic var onslot_1: Int
39     @NSManaged dynamic var onslot_2: Int
40     @NSManaged dynamic var onslot_3: Int
41     @NSManaged dynamic var onslot_4: Int
42     @NSManaged dynamic var raisou_0: Int
43     @NSManaged dynamic var raisou_1: Int
44     @NSManaged dynamic var sakuteki_0: Int
45     @NSManaged dynamic var sakuteki_1: NSNumber?
46     @NSManaged dynamic var sally_area: NSNumber?
47     @NSManaged dynamic var ship_id: Int
48     @NSManaged dynamic var slot_0: Int
49     @NSManaged dynamic var slot_1: Int
50     @NSManaged dynamic var slot_2: Int
51     @NSManaged dynamic var slot_3: Int
52     @NSManaged dynamic var slot_4: Int
53     @NSManaged dynamic var slot_ex: Int
54     @NSManaged dynamic var soku: Int
55     @NSManaged dynamic var sortno: NSNumber?
56     @NSManaged dynamic var soukou_0: Int
57     @NSManaged dynamic var soukou_1: Int
58     @NSManaged dynamic var srate: NSNumber?
59     @NSManaged dynamic var taiku_0: Int
60     @NSManaged dynamic var taiku_1: Int
61     @NSManaged dynamic var taisen_0: Int
62     @NSManaged dynamic var taisen_1: NSNumber?
63     @NSManaged dynamic var equippedItem: NSOrderedSet
64     @NSManaged dynamic var master_ship: MasterShip
65     @NSManaged dynamic var extraItem: SlotItem?
66 }
67 // swiftlint:eable identifier_name
68
69 private let shortSTypeNames: [String] = {
70     
71     guard let url = Bundle.main.url(forResource: "STypeShortName", withExtension: "plist"),
72         let array = NSArray(contentsOf: url) as? [String] else {
73             
74             Logger.shared.log("Can not load STypeShortName.plist.")
75             
76             return []
77     }
78     
79     return array
80 }()
81
82 private let levelUpExps: [Int] = {
83     
84     guard let url = Bundle.main.url(forResource: "LevelUpExp", withExtension: "plist"),
85         let array = NSArray(contentsOf: url) as? [Int] else {
86             
87             Logger.shared.log("Can not load LevelUpExp.plist.")
88             
89             return []
90     }
91     
92     return array
93 }()
94
95 extension Ship {
96     
97     @objc override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> {
98         
99         switch key {
100             
101         case #keyPath(name): return [#keyPath(ship_id)]
102             
103         case #keyPath(shortTypeName): return [#keyPath(ship_id)]
104             
105         case #keyPath(next): return [#keyPath(exp)]
106             
107         case #keyPath(status): return [#keyPath(nowhp), #keyPath(maxhp)]
108         
109         case #keyPath(planColor): return [#keyPath(sally_area)]
110             
111         case #keyPath(isMaxKaryoku): return [#keyPath(karyoku_1), #keyPath(kyouka_0)]
112             
113         case #keyPath(isMaxRaisou): return [#keyPath(raisou_1), #keyPath(kyouka_1)]
114             
115         case #keyPath(isMaxTaiku): return [#keyPath(taiku_1), #keyPath(kyouka_2)]
116             
117         case #keyPath(isMaxSoukou): return [#keyPath(soukou_1), #keyPath(kyouka_3)]
118             
119         case #keyPath(isMaxLucky): return [#keyPath(lucky_1), #keyPath(kyouka_4)]
120             
121         case #keyPath(upgradeLevel): return [#keyPath(ship_id)]
122             
123         case #keyPath(upgradeExp): return [#keyPath(exp)]
124             
125         case #keyPath(steelRequiredInRepair): return [#keyPath(nowhp)]
126             
127         case #keyPath(fuelRequiredInRepair): return [#keyPath(nowhp)]
128             
129         case #keyPath(seiku): return [#keyPath(slot_0), #keyPath(slot_1), #keyPath(slot_2), #keyPath(slot_3), #keyPath(slot_4),
130                                       #keyPath(onslot_0), #keyPath(onslot_1), #keyPath(onslot_2), #keyPath(onslot_3), #keyPath(onslot_4)]
131             
132         default: return []
133             
134         }
135     }
136     
137     @objc dynamic var name: String { return master_ship.name }
138     
139     @objc dynamic var shortTypeName: String? {
140         
141         let index = master_ship.stype.id - 1
142         
143         guard case 0..<shortSTypeNames.count = index else {
144             
145             return nil
146         }
147         
148         return shortSTypeNames[index]
149     }
150     
151     @objc dynamic var next: NSNumber? {
152         
153         guard case 0..<levelUpExps.count = lv else {
154             
155             return nil
156         }
157         
158         if lv == 99 {
159             
160             return nil
161         }
162         
163         let nextExp = levelUpExps[lv]
164         
165         if lv < 99 {
166             
167             return (nextExp - exp) as NSNumber
168         }
169         
170         return (1_000_000 + nextExp - exp) as NSNumber
171     }
172     
173     @objc dynamic var status: Int {
174         
175         switch Double(nowhp) / Double(maxhp) {
176             
177         case (0...0.25): return 3
178             
179         case (0.25...0.50): return 2
180             
181         case (0.50...0.75): return 1
182             
183         default: return 0
184             
185         }
186     }
187     
188     @objc dynamic var planColor: NSColor {
189         
190         if !UserDefaults.standard[.showsPlanColor] {
191             
192             return .controlTextColor
193         }
194         
195         guard let sally = sally_area else {
196             
197             return .controlTextColor
198         }
199         
200         switch sally {
201             
202         case 1: return UserDefaults.standard[.plan01Color]
203             
204         case 2: return UserDefaults.standard[.plan02Color]
205             
206         case 3: return UserDefaults.standard[.plan03Color]
207             
208         case 4: return UserDefaults.standard[.plan04Color]
209             
210         case 5: return UserDefaults.standard[.plan05Color]
211             
212         case 6: return UserDefaults.standard[.plan06Color]
213             
214         default: return .controlTextColor
215             
216         }
217     }
218 }
219
220
221 extension Ship {
222     
223     @objc dynamic var maxBull: Int { return master_ship.bull_max }
224     @objc dynamic var maxFuel: Int { return master_ship.fuel_max }
225     
226     @objc dynamic var isMaxKaryoku: Bool {
227         
228         let initial = master_ship.houg_0
229         let max = karyoku_1
230         let growth = kyouka_0
231         
232         return initial + growth >= max
233     }
234     
235     @objc dynamic var isMaxRaisou: Bool {
236         
237         let initial = master_ship.raig_0
238         let max = raisou_1
239         let growth = kyouka_1
240         
241         return initial + growth >= max
242     }
243     
244     @objc dynamic var isMaxTaiku: Bool {
245         
246         let initial = master_ship.tyku_0
247         let max = taiku_1
248         let growth = kyouka_2
249         
250         return initial + growth >= max
251     }
252     
253     @objc dynamic var isMaxSoukou: Bool {
254         
255         let initial = master_ship.souk_0
256         let max = soukou_1
257         let growth = kyouka_3
258         
259         return initial + growth >= max
260     }
261     
262     @objc dynamic var isMaxLucky: Bool {
263         
264         let initial = master_ship.luck_0
265         let max = lucky_1
266         let growth = kyouka_4
267         
268         return initial + growth >= max
269     }
270     
271     @objc dynamic var upgradeLevel: Int { return master_ship.afterlv }
272     
273     @objc dynamic var upgradeExp: NSNumber? {
274         
275         let upgradeLv = upgradeLevel
276         
277         if upgradeLv <= 0 {
278             
279             return nil
280         }
281         if levelUpExps.count < upgradeLv {
282             
283             return nil
284         }
285         
286         let upExp = levelUpExps[upgradeLv - 1] - exp
287         
288         return upExp < 0 ? 0 : upExp as NSNumber
289     }
290     
291     @objc dynamic var guardEscaped: Bool {
292         
293         let store = TemporaryDataStore.default
294         
295         guard let _ = store.ensuredGuardEscaped(byShipId: id) else {
296             
297             return false
298         }
299         
300         return true
301     }
302     
303     @objc dynamic var steelRequiredInRepair: Int {
304         
305         return Int(Double(maxFuel) * 0.06 * Double(maxhp - nowhp))
306     }
307     
308     @objc dynamic var fuelRequiredInRepair: Int {
309         
310         return Int(Double(maxFuel) * 0.032 * Double(maxhp - nowhp))
311     }
312 }
313
314 extension Ship {
315     
316     func setItem(_ id: Int, to slot: Int) {
317         
318         switch slot {
319             
320         case 0: slot_0 = id
321             
322         case 1: slot_1 = id
323             
324         case 2: slot_2 = id
325             
326         case 3: slot_3 = id
327             
328         case 4: slot_4 = id
329             
330         default: fatalError("Ship: setItem out of bounds.")
331             
332         }
333     }
334     
335     func slotItemId(_ index: Int) -> Int {
336         
337         switch index {
338             
339         case 0: return slot_0
340             
341         case 1: return slot_1
342             
343         case 2: return slot_2
344             
345         case 3: return slot_3
346             
347         case 4: return slot_4
348             
349         default: return 0
350             
351         }
352     }
353     
354     func slotItemCount(_ index: Int) -> Int {
355         
356         switch index {
357             
358         case 0: return onslot_0
359             
360         case 1: return onslot_1
361             
362         case 2: return onslot_2
363             
364         case 3: return onslot_3
365             
366         case 4: return onslot_4
367             
368         default: return 0
369             
370         }
371     }
372     
373     func slotItemMax(_ index: Int) -> Int {
374         
375         switch index {
376             
377         case 0: return master_ship.maxeq_0
378             
379         case 1: return master_ship.maxeq_1
380             
381         case 2: return master_ship.maxeq_2
382             
383         case 3: return master_ship.maxeq_3
384             
385         case 4: return master_ship.maxeq_4
386             
387         default: return 0
388             
389         }
390     }
391     
392     func slotItem(_ index: Int) -> SlotItem? {
393         
394         return ServerDataStore.default.slotItem(by: slotItemId(index))
395     }
396     
397     @objc dynamic var totalEquipment: Int {
398         
399         return (0...4).map(slotItemMax).reduce(0, +)
400     }
401     
402     @objc dynamic var seiku: Int {
403         
404         return SeikuCalclator(ship: self).seiku
405     }
406     
407 }