1use crate::abilities::AbilityId;
2use crate::bundles::BundleId;
3use crate::dungeons::DungeonTemplateId;
4use crate::entity::{Coordinates, Entity, EntityId};
5use crate::game::EntityTemplateId;
6use crate::pets::PetId;
7
8use crate::prelude::*;
9
10use strum_macros::{Display, EnumString};
11
12#[derive(
13 Clone,
14 Debug,
15 Default,
16 Serialize,
17 Deserialize,
18 PartialEq,
19 Eq,
20 Tsify,
21 EnumString,
22 Display,
23 JsonSchema,
24)]
25#[tsify(from_wasm_abi, into_wasm_abi)]
26pub enum EntityTeam {
27 #[default]
28 Ally,
29 Enemy,
30}
31
32impl CustomType for EntityTeam {
33 fn build(mut builder: TypeBuilder<Self>) {
34 builder
35 .with_name("EntityTeam")
36 .with_fn("EntityTeam", |team: &str| {
37 if team == "Ally" {
38 Self::Ally
39 } else {
40 Self::Enemy
41 }
42 })
43 .with_get("str", |et: &mut EntityTeam| EntityTeam::to_string(et));
44 }
45}
46
47#[derive(
48 Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Tsify, Display, JsonSchema,
49)]
50#[tsify(from_wasm_abi, into_wasm_abi)]
51pub enum EntityType {
52 #[schemars(title = "ПВЕ юнит")]
53 PVEEntity {
54 #[schemars(title = "ID юнита", schema_with = "entity_link_id_schema")]
55 entity_template_id: EntityTemplateId,
56 },
57 #[default]
58 #[schemars(title = "ПВП юнит")]
59 PVPEntity,
60}
61
62#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Tsify, JsonSchema)]
63pub struct FightEntity {
64 #[schemars(title = "Тип юнита")]
65 pub entity_type: EntityType,
66 #[schemars(title = "Координаты юнита")]
67 pub position: Coordinates,
68 #[schemars(title = "Нужна ли отрисовка большого хп бара")]
69 pub has_big_hp_bar: bool,
70 #[schemars(title = "Команда юнита")]
71 pub team: EntityTeam,
72}
73
74#[derive(
75 Clone,
76 Debug,
77 Default,
78 Serialize,
79 Deserialize,
80 PartialEq,
81 Eq,
82 Tsify,
83 EnumString,
84 Display,
85 JsonSchema,
86)]
87#[tsify(from_wasm_abi, into_wasm_abi)]
88pub enum FightType {
89 #[default]
90 CampaignFight,
91 CampaignBossFight,
92 ArenaPVP,
93 VassalPVP,
94 SingleFight,
95}
96
97#[declare]
98pub type FightTemplateId = Uuid;
99
100#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Tsify, JsonSchema, CustomType)]
101pub struct FightTemplate {
102 #[schemars(schema_with = "id_schema")]
103 pub id: FightTemplateId,
104
105 #[schemars(title = "Название боя")]
106 pub title: i18n::I18nString,
107
108 #[schemars(title = "Мощь боя")]
109 pub power: Option<u64>,
110
111 #[schemars(title = "Все существа в бою")]
114 pub fight_entities: Vec<FightEntity>,
115
116 #[schemars(title = "Максимальная длительность боя в тиках")]
117 pub max_duration_ticks: u64,
118
119 #[schemars(title = "Целевая ширина экрана (в клетках)")]
120 pub target_width_cells: u64,
121
122 #[schemars(title = "Fx на старте боя")]
123 pub starting_fx: String,
125
126 #[schemars(title = "Тип боя")]
127 pub fight_type: FightType,
128
129 #[schemars(title = "Количество волн в бою")]
130 pub waves_amount: i64,
131
132 #[schemars(title = "Скрипт для подготовки боя", schema_with = "script_schema")]
133 pub prepare_fight_script: String,
134
135 #[schemars(title = "Скрипт для начала боя", schema_with = "script_schema")]
136 pub start_script: String,
137
138 #[schemars(title = "Задник", schema_with = "aa_background_schema")]
139 pub background: String,
140
141 #[schemars(
142 title = "Время ожидания перед стартом следующего боя в тиках",
143 description = "Это момент анимации перебежки персонажа между битвами"
144 )]
145 pub start_fight_delay_ticks: Option<u64>,
146
147 #[schemars(
148 title = "Время ожидания перед стартом уже начавшегося боя в случае победы",
149 description = "Это момент, когда враги выбегают на экран"
150 )]
151 pub prepare_fight_win_duration_ticks: Option<u64>,
152
153 #[schemars(
154 title = "Время ожидания перед стартом уже начавшегося боя в случае поражения",
155 description = "Это момент, когда враги выбегают на экран"
156 )]
157 pub prepare_fight_lose_duration_ticks: Option<u64>,
158
159 #[schemars(title = "Время ожидания перед окончанием боя")]
160 pub end_fight_delay_ticks: Option<u64>,
161
162 #[schemars(
163 title = "Бандл награды за победу в бою",
164 schema_with = "option_bundle_id_schema"
165 )]
166 pub bundle_reward_id: Option<BundleId>,
167
168 #[schemars(title = "Останавливать ли бой после победы")]
169 pub stop_on_win: bool,
170
171 #[schemars(title = "Останавливать ли бой после поражения")]
172 pub stop_on_lose: bool,
173
174 #[schemars(title = "Показывать ли VS экран в начале боя")]
175 pub show_vs_screen: bool,
176
177 #[schemars(title = "Показывать ли стейджи")]
178 pub show_stages: Option<bool>,
179}
180
181#[derive(
182 Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Tsify, JsonSchema, CustomType,
183)]
184pub struct ActiveDungeon {
185 pub id: DungeonTemplateId,
186 pub difficulty: i64,
187}
188
189#[derive(
190 Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Tsify, JsonSchema, CustomType,
191)]
192pub struct ActivePetAbility {
193 pub pet_template_id: PetId,
194 pub ability_id: AbilityId,
195 pub charge: i64,
196 pub max_charge: i64,
197}
198
199#[derive(
200 Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Tsify, JsonSchema, CustomType,
201)]
202pub struct ActiveFight {
203 pub id: uuid::Uuid,
204 pub fight_id: FightTemplateId,
205 pub current_wave: i64,
206 pub player_id: EntityId,
207 pub party_player_id: Option<EntityId>,
208 pub entities: Vec<Entity>,
209 pub fight_stopped: bool,
210 pub fight_ended: bool,
211 pub max_duration_ticks: u64,
212 pub dungeon: Option<ActiveDungeon>,
213 pub paused: bool,
214 pub pet_combat_state: Option<ActivePetAbility>,
215 pub leader_pet_template_id: Option<PetId>,
216}
217
218impl ActiveFight {
219 pub fn get_player(&self) -> Option<&Entity> {
220 self.entities
221 .iter()
222 .find(|entity| entity.id == self.player_id)
223 }
224
225 pub fn get_player_mut(&mut self) -> Option<&mut Entity> {
226 self.entities
227 .iter_mut()
228 .find(|entity| entity.id == self.player_id)
229 }
230
231 pub fn get_party_player(&self) -> Option<&Entity> {
232 let party_id = self.party_player_id?;
233 self.entities.iter().find(|entity| entity.id == party_id)
234 }
235
236 pub fn get_party_player_mut(&mut self) -> Option<&mut Entity> {
237 let party_id = self.party_player_id?;
238 self.entities
239 .iter_mut()
240 .find(|entity| entity.id == party_id)
241 }
242
243 pub fn get_enemies_amount(&self) -> usize {
244 self.entities
245 .iter()
246 .filter(|entity| entity.team == EntityTeam::Enemy)
247 .count()
248 }
249}