OSDN Git Service

968d4f4b5799aac8fd6636bd906a97d27799d152
[kcd/KCD.git] / KCD / CalculateDamageCommand.swift
1 //
2 //  CalculateDamageCommand.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2017/01/15.
6 //  Copyright © 2017年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10 import SwiftyJSON
11
12 enum BattleType {
13     
14     case normal
15     case combinedAir
16     case combinedWater
17     case eachCombinedAir
18     case eachCombinedWater
19     case enemyCombined
20 }
21
22 enum DamageControlID: Int {
23     
24     case damageControl = 42
25     case goddes = 43
26 }
27
28 final class CalculateDamageCommand: JSONCommand {
29     
30     override func execute() {
31         
32         guard let battleApi = BattleAPI(rawValue: api) else { return }
33         
34         switch battleApi {
35         case .battle, .airBattle, .ldAirBattle:
36             normalBattle(battleType: .normal)
37             
38         case .combinedEcBattle:
39             enemyCombinedBattle(battleType: .enemyCombined)
40             
41         case .combinedBattle, .combinedAirBattle:
42             combinedAirBattle(battleType: .combinedAir)
43             
44         case .combinedBattleWater, .combinedLdAirBattle:
45             normalBattle(battleType: .combinedWater)
46             
47         case .combinedEachBattle:
48             eachAirBattle(battleType: .eachCombinedAir)
49             
50         case .combinedEachBattleWater:
51             normalBattle(battleType: .eachCombinedWater)
52             
53         case .midnightBattle, .midnightSpMidnight:
54             midnightBattle(battleType: .normal)
55             
56         case .combinedMidnightBattle, .combinedSpMidnight:
57             midnightBattle(battleType: .combinedAir)
58             
59         case .combinedEcMidnightBattle:
60             midnightBattle(battleType: .eachCombinedAir)
61             
62         case .battleResult, .combinedBattleResult:
63             applyDamage()
64             resetDamage()
65         }
66     }
67     
68     func normalBattle(battleType: BattleType) {
69         
70         updateBattleCell()
71         DamageCalculator(json, battleType).calculateBattle()
72     }
73     
74     func combinedAirBattle(battleType: BattleType) {
75         
76         updateBattleCell()
77         DamageCalculator(json, battleType).calcCombinedBattleAir()
78     }
79     
80     func eachAirBattle(battleType: BattleType) {
81         
82         updateBattleCell()
83         DamageCalculator(json, battleType).calcEachBattleAir()
84     }
85     
86     func enemyCombinedBattle(battleType: BattleType) {
87         
88         updateBattleCell()
89         DamageCalculator(json, battleType).calcEnemyCombinedBattle()
90     }
91     
92     func midnightBattle(battleType: BattleType) {
93         
94         DamageCalculator(json, battleType).calcMidnight()
95     }
96 }
97
98 extension CalculateDamageCommand {
99     
100     func resetDamage() {
101         
102         let store = TemporaryDataStore.oneTimeEditor()
103         
104         store.damages().forEach(store.delete)
105     }
106     
107     func applyDamage() {
108         
109         let store = TemporaryDataStore.oneTimeEditor()
110         
111         let totalDamages = store.sortedDamagesById()
112         
113         let aStore = ServerDataStore.oneTimeEditor()
114         
115         // 第二艦隊単独出撃で正しくデータが反映されるように逆順にして計算
116         totalDamages.reversed().forEach {
117             
118             guard let ship = aStore.ship(by: $0.shipID) else { return }
119             
120             if ship.nowhp != $0.hp {
121                 
122                 Debug.print("\(ship.name)(\(ship.id)),HP \(ship.nowhp) -> \($0.hp)", level: .debug)
123             }
124             
125             ship.nowhp = $0.hp
126             
127             if $0.useDamageControl { removeFirstDamageControl(of: ship) }
128         }
129         
130         Debug.print("------- End Battle", level: .debug)
131     }
132     
133     func updateBattleCell() {
134         
135         let store = TemporaryDataStore.default
136         
137         guard let battle = store.battle() else { return Logger.shared.log("Battle is invalid.") }
138         
139         battle.battleCell = (battle.no == 0 ? nil : battle.no as NSNumber)
140         
141         Debug.excute(level: .debug) {
142             
143             print("Enter Cell ------- ")
144             
145             if let seiku = json["api_data"]["api_kouku"]["api_stage1"]["api_disp_seiku"].int {
146                 
147                 switch seiku {
148                 case 0: print("制空権 均衡")
149                 case 1: print("制空権 確保")
150                 case 2: print("制空権 優勢")
151                 case 3: print("制空権 劣勢")
152                 case 4: print("制空権 喪失")
153                 default: break
154                 }
155             }
156             
157             if let intercept = json["api_data"]["api_formation"][2].int {
158                 
159                 switch intercept {
160                 case 1: print("交戦形態 同航戦")
161                 case 2: print("交戦形態 反航戦")
162                 case 3: print("交戦形態 T字戦有利")
163                 case 4: print("交戦形態 T字戦不利")
164                 default: break
165                 }
166             }
167         }
168     }
169     
170     func removeFirstDamageControl(of ship: Ship) {
171         
172         let store = ServerDataStore.default
173         
174         let (item, damageControl) = ship
175             .equippedItem
176             .lazy
177             .flatMap { $0 as? SlotItem }
178             .map { ($0, store.masterSlotItemID(by: $0.id)) }
179             .map { ($0.0, DamageControlID(rawValue: $0.1)) }
180             .filter { $0.1 != nil }
181             .first ?? (nil, nil)
182         
183         if let validDamageControl = damageControl {
184             
185             switch validDamageControl {
186             case .damageControl: break
187                 
188             case .goddes:
189                 ship.fuel = ship.maxFuel
190                 ship.bull = ship.maxBull
191             }
192             
193             guard let equiped = ship.equippedItem.array as? [SlotItem] else { return }
194                 
195             ship.equippedItem = NSOrderedSet(array: equiped.filter { $0 != item })
196             
197             return
198         }
199         
200         // check extra slot
201         let exItemId = store.masterSlotItemID(by: ship.slot_ex)
202         
203         guard let exType = DamageControlID(rawValue: exItemId) else { return }
204         
205         switch exType {
206         case .damageControl: break
207             
208         case .goddes:
209             ship.fuel = ship.maxFuel
210             ship.bull = ship.maxBull
211         }
212         
213         ship.slot_ex = -1
214     }
215 }