comparison src/th06/ecl_vm.rs @ 660:31fc0d881105

Make ecl_vm compile, and use it in eclrenderer (doesn’t render yet).
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Sat, 10 Aug 2019 14:41:30 +0200
parents 53786d834444
children 598f3125cbac
comparison
equal deleted inserted replaced
659:53786d834444 660:31fc0d881105
1 //! ECL runner. 1 //! ECL runner.
2 2
3 use crate::th06::anm0::{ 3 use crate::th06::ecl::{Ecl, SubInstruction};
4 Script, 4 use crate::th06::enemy::Enemy;
5 Anm0,
6 Call,
7 Instruction,
8 };
9 use crate::th06::interpolator::{Interpolator1, Interpolator2, Interpolator3, Formula};
10 use crate::util::math::Mat4;
11 use crate::util::prng::Prng; 5 use crate::util::prng::Prng;
12 use std::cell::RefCell; 6 use std::cell::RefCell;
13 use std::rc::{Rc, Weak}; 7 use std::rc::Rc;
14 8
15 fn run_instruction(&mut self, instruction: Instruction) { 9 type Variables = ([i32; 4], [f32; 4], [i32; 4]);
16 let mut sprite = self.sprite.borrow_mut(); 10
11 /// Interpreter for enemy scripts.
12 #[derive(Default)]
13 pub struct EclRunner {
14 enemy: Rc<RefCell<Enemy>>,
15 ecl: Option<Ecl>,
16 sub: u8,
17 running: bool,
18 /// XXX
19 pub frame: i32,
20 ip: i32,
21 variables: Variables,
22 comparison_reg: i8,
23 stack: Vec<Variables>,
24 }
25
26 impl EclRunner {
27 /// Create a new ECL runner.
28 pub fn new(ecl: &Ecl, enemy: Rc<RefCell<Enemy>>, sub: u8) -> EclRunner {
29 EclRunner {
30 enemy,
31 // XXX: no clone.
32 ecl: Some(ecl.clone()),
33 sub,
34 ..Default::default()
35 }
36 }
37
38 /// Advance the ECL of a single frame.
39 pub fn run_frame(&mut self) {
40 while self.running {
41 let ecl = self.ecl.clone().unwrap();
42 let sub = &ecl.subs[self.sub as usize];
43 let call = match sub.instructions.get(self.ip as usize) {
44 Some(call) => call,
45 None => {
46 self.running = false;
47 break;
48 }
49 };
50
51 if call.time > self.frame {
52 break;
53 }
54 self.ip += 1;
55
56 let rank = self.enemy.borrow().get_rank();
57 if call.rank_mask & (0x100 << rank) == 0 {
58 continue;
59 }
60
61 if call.time == self.frame {
62 self.run_instruction(call.instr.clone());
63 }
64 }
65 self.frame += 1;
66 }
67
68 fn get_i32(&self, var: i32) -> i32 {
69 let enemy = self.enemy.borrow();
70 match var {
71 -10001 => self.variables.0[0],
72 -10002 => self.variables.0[1],
73 -10003 => self.variables.0[2],
74 -10004 => self.variables.0[3],
75 -10005 => self.variables.1[0] as i32,
76 -10006 => self.variables.1[1] as i32,
77 -10007 => self.variables.1[2] as i32,
78 -10008 => self.variables.1[3] as i32,
79 -10009 => self.variables.2[0],
80 -10010 => self.variables.2[1],
81 -10011 => self.variables.2[2],
82 -10012 => self.variables.2[3],
83 -10013 => enemy.get_rank(),
84 -10014 => enemy.get_difficulty(),
85 -10015 => enemy.pos.x as i32,
86 -10016 => enemy.pos.y as i32,
87 -10017 => enemy.z as i32,
88 -10018 => unimplemented!(),
89 -10019 => unimplemented!(),
90 -10020 => unreachable!(),
91 -10021 => unimplemented!(),
92 -10022 => enemy.frame as i32,
93 -10023 => unreachable!(),
94 -10024 => enemy.life as i32,
95 -10025 => unimplemented!(),
96 _ => var
97 }
98 }
99
100 fn get_f32(&self, var: f32) -> f32 {
101 let enemy = self.enemy.borrow();
102 match var {
103 -10001.0 => self.variables.0[0] as f32,
104 -10002.0 => self.variables.0[1] as f32,
105 -10003.0 => self.variables.0[2] as f32,
106 -10004.0 => self.variables.0[3] as f32,
107 -10005.0 => self.variables.1[0],
108 -10006.0 => self.variables.1[1],
109 -10007.0 => self.variables.1[2],
110 -10008.0 => self.variables.1[3],
111 -10009.0 => self.variables.2[0] as f32,
112 -10010.0 => self.variables.2[1] as f32,
113 -10011.0 => self.variables.2[2] as f32,
114 -10012.0 => self.variables.2[3] as f32,
115 -10013.0 => enemy.get_rank() as f32,
116 -10014.0 => enemy.get_difficulty() as f32,
117 -10015.0 => enemy.pos.x,
118 -10016.0 => enemy.pos.y,
119 -10017.0 => enemy.z,
120 -10018.0 => unimplemented!(),
121 -10019.0 => unimplemented!(),
122 -10020.0 => unreachable!(),
123 -10021.0 => unimplemented!(),
124 -10022.0 => enemy.frame as f32,
125 -10023.0 => unreachable!(),
126 -10024.0 => enemy.life as f32,
127 -10025.0 => unimplemented!(),
128 _ => var
129 }
130 }
131
132 fn set_i32(&mut self, var: i32, value: i32) {
133 unimplemented!()
134 }
135
136 fn set_f32(&mut self, var: f32, value: f32) {
137 unimplemented!()
138 }
139
140 fn get_prng(&mut self) -> Rc<RefCell<Prng>> {
141 let enemy = self.enemy.borrow();
142 enemy.prng.upgrade().unwrap()
143 }
144
145 fn run_instruction(&mut self, instruction: SubInstruction) {
17 match instruction { 146 match instruction {
18 Instruction::Noop() { 147 SubInstruction::Noop() => {
19 // really 148 // really
20 } 149 }
21 // 1 150 // 1
22 Instruction::Stop() { 151 SubInstruction::Destroy(_unused) => {
23 self._enemy.removed = true; 152 let mut enemy = self.enemy.borrow_mut();
24 } 153 enemy.removed = true;
25 // 2 154 }
26 Instruction::RelativeJump(frame, ip) { 155 // 2
156 SubInstruction::RelativeJump(frame, ip) => {
27 self.frame = frame; 157 self.frame = frame;
28 // ip = ip + flag in th06 158 // ip = ip + flag in th06
29 self.ip = ip; 159 self.ip = ip;
30 // we jump back to the main of the interpreter 160 // we jump back to the main of the interpreter
31 } 161 }
32 // 3 162 // 3
33 // GHIDRA SAYS THERE IS A COMPARISON_REG BUFFER BUT THERE IS NOT!!! 163 // GHIDRA SAYS THERE IS A COMPARISON_REG BUFFER BUT THERE IS NOT!!!
34 // 164 //
35 // MOV ECX,dword ptr [EBP + 0x8] jumptable 00407544 case 31 165 // MOV ECX,dword ptr [EBP + 0x8] jumptable 00407544 case 31
36 // CMP dword ptr [0x9d4 + ECX],0x0 166 // CMP dword ptr [0x9d4 + ECX],0x0
37 // JLE LAB_00407abb 167 // JLE LAB_00407abb
38 // aka ECX = enemy pointer 168 // aka ECX = enemy pointer
39 // ECX->9d4 (aka enemy_pointer_copy->comparison_reg) == 0 169 // ECX->9d4 (aka enemy_pointer_copy->comparison_reg) == 0
40 // only the pointer is copied, not the value, thus we are safe 170 // only the pointer is copied, not the value, thus we are safe
41 Instruction::RelativeJumpEx(frame, ip, var_id) { 171 SubInstruction::RelativeJumpEx(frame, ip, var_id) => {
42 // TODO: counter_value is a field of "enemy" in th06, to check 172 // TODO: counter_value is a field of "enemy" in th06, to check
43 counter_value = self._getval(var_id) - 1 173 let counter_value = self.get_i32(var_id) - 1;
44 if counter_value > 0 { 174 if counter_value > 0 {
45 Instruction::RelativeJump(frame, ip); 175 SubInstruction::RelativeJump(frame, ip);
46 } 176 }
47 } 177 }
48 178 // 4
49 //4, 5 179 SubInstruction::SetInt(var_id, value) => {
50 Instruction::SetVariable(var_id, value) { 180 self.set_i32(var_id, value);
51 self._setval(var_id, value); 181 }
182 // 5
183 SubInstruction::SetFloat(var_id, value) => {
184 self.set_f32(var_id as f32, value);
52 } 185 }
53 // 6 186 // 6
54 Instruction::SetRandomInt(var_id, maxval) { 187 SubInstruction::SetRandomInt(var_id, maxval) => {
55 self._setval(var_id, self._game.prng.rand_32()%self._getval(maxval)); 188 let random = self.get_prng().borrow_mut().get_u32() as i32;
189 self.set_i32(var_id, random % self.get_i32(maxval));
56 } 190 }
57 // 7 191 // 7
58 Instruction::SetRandomIntMin(var_id, maxval, minval) { 192 /*
59 self._setval(var_id, (self._game.prng.rand_32()%self._getval(maxval))+self._getval(minval)); 193 SubInstruction::SetRandomIntMin(var_id, maxval, minval) => {
60 } 194 self.set_i32(var_id, (self.get_prng().borrow_mut().get_u32() % self.get_i32(maxval)) + self.get_i32(minval));
195 }
196 */
61 // 8 197 // 8
62 Instruction::SetRandomFloat(var_id, maxval) { 198 SubInstruction::SetRandomFloat(var_id, maxval) => {
63 self._setval(var_id, self._getval(maxval) * self._game.prng.rand_double()) 199 let random = self.get_prng().borrow_mut().get_f64() as f32;
200 self.set_f32(var_id as f32, self.get_f32(maxval) * random)
64 } 201 }
65 // 9 202 // 9
66 Instruction::SetRandomFloatMin(var_id, maxval, minval) { 203 SubInstruction::SetRandomFloatMin(var_id, maxval, minval) => {
67 self._setval(var_id, (self._getval(maxval) * self._game.prng.rand_double())+self._getval(minval)) 204 let random = self.get_prng().borrow_mut().get_f64() as f32;
205 self.set_f32(var_id as f32, self.get_f32(maxval) * random + self.get_f32(minval))
68 } 206 }
69 // 10 207 // 10
70 Instruction::StoreX(var_id) { 208 SubInstruction::StoreX(var_id) => {
71 self._setval(var_id, self._enemy.x); 209 let x = {
210 let enemy = self.enemy.borrow();
211 enemy.pos.x
212 };
213 // TODO: is this really an i32?
214 self.set_i32(var_id, x as i32);
72 } 215 }
73 // 11 216 // 11
74 Instruction::StoreY(var_id) { 217 /*
75 self._setval(var_id, self._enemy.y); 218 SubInstruction::StoreY(var_id) => {
76 } 219 let enemy = self.enemy.borrow();
220 self.set_i32(var_id, enemy.pos.y);
221 }
222 */
77 // 12 223 // 12
78 Instruction::StoreZ(var_id) { 224 /*
79 self._setval(var_id, self._enemy.z); 225 SubInstruction::StoreZ(var_id) => {
80 } 226 let enemy = self.enemy.borrow();
227 self.set_i32(var_id, enemy.z);
228 }
229 */
81 // 13(int), 20(float), same impl in th06 230 // 13(int), 20(float), same impl in th06
82 Instruction::Add(var_id, a, b) { 231 SubInstruction::AddInt(var_id, a, b) => {
83 self._setval(var_id, self._getval(a) + self._getval(b)); 232 self.set_i32(var_id, self.get_i32(a) + self.get_i32(b));
233 }
234 SubInstruction::AddFloat(var_id, a, b) => {
235 self.set_f32(var_id as f32, self.get_f32(a) + self.get_f32(b));
84 } 236 }
85 // 14(int), 21(float), same impl in th06 237 // 14(int), 21(float), same impl in th06
86 Instruction::Substract(var_id, a, b) { 238 SubInstruction::SubstractInt(var_id, a, b) => {
87 self._setval(var_id, self._getval(a) - self._getval(b)); 239 self.set_i32(var_id, self.get_i32(a) - self.get_i32(b));
240 }
241 SubInstruction::SubstractFloat(var_id, a, b) => {
242 self.set_f32(var_id as f32, self.get_f32(a) - self.get_f32(b));
88 } 243 }
89 // 15(int), 22(unused) 244 // 15(int), 22(unused)
90 Instruction::Multiply(var_id, a, b) { 245 SubInstruction::MultiplyInt(var_id, a, b) => {
91 self._setval(var_id, self._getval(a) * self._getval(b)); 246 self.set_i32(var_id, self.get_i32(a) * self.get_i32(b));
92 } 247 }
248 /*
249 SubInstruction::MultiplyFloat(var_id, a, b) => {
250 self.set_f32(var_id as f32, self.get_f32(a) * self.get_f32(b));
251 }
252 */
93 // 16(int), 23(unused) 253 // 16(int), 23(unused)
94 Instruction::Divide(var_id, a, b) { 254 SubInstruction::DivideInt(var_id, a, b) => {
95 self._setval(var_id, self._getval(a) / self._getval(b)); 255 self.set_i32(var_id, self.get_i32(a) / self.get_i32(b));
96 } 256 }
257 /*
258 SubInstruction::Divide(var_id, a, b) => {
259 self.set_f32(var_id as f32, self.get_f32(a) / self.get_f32(b));
260 }
261 */
97 // 17(int) 24(unused) 262 // 17(int) 24(unused)
98 Instruction::Divide(var_id, a, b) { 263 SubInstruction::ModuloInt(var_id, a, b) => {
99 self._setval(var_id, self._getval(a) % self._getval(b)); 264 self.set_i32(var_id, self.get_i32(a) % self.get_i32(b));
100 } 265 }
266 /*
267 SubInstruction::ModuloFloat(var_id, a, b) => {
268 self.set_f32(var_id as f32, self.get_f32(a) % self.get_f32(b));
269 }
270 */
101 // 18 271 // 18
102 // setval used by pytouhou, but not in game(???) 272 // setval used by pytouhou, but not in game(???)
103 Instruction::Increment(var_id) { 273 SubInstruction::Increment(var_id) => {
104 var_id = self._getval(var_id) + 1 274 self.set_i32(var_id, self.get_i32(var_id) + 1);
105 } 275 }
106 // 19 276 // 19
107 Instruction::Decrement(var_id) { 277 /*
108 var_id = self._getval(var_id) - 1 278 SubInstruction::Decrement(var_id) => {
109 } 279 self.set_i32(var_id, self.get_i32(var_id) - 1);
280 }
281 */
110 //25 282 //25
111 Instruction::GetDirection(var_id, x1, y1, x2, y2) { 283 SubInstruction::GetDirection(var_id, x1, y1, x2, y2) => {
112 //__ctrandisp2 in ghidra, let's assume from pytouhou it's atan2 284 //__ctrandisp2 in ghidra, let's assume from pytouhou it's atan2
113 self._setval(var_id, atan2(self._getval(y2) - self._getval(y1), self._getval(x2) - self._getval(x1))); 285 self.set_f32(var_id as f32, (self.get_f32(y2) - self.get_f32(y1)).atan2(self.get_f32(x2) - self.get_f32(x1)));
114 } 286 }
115 287
116 // 26 288 // 26
117 Instruction::FloatToUnitCircle(var_id) { 289 SubInstruction::FloatToUnitCircle(var_id) => {
118 // TODO: atan2(var_id, ??) is used by th06, maybe ?? is pi? 290 // TODO: atan2(var_id, ??) is used by th06, maybe ?? is pi?
119 // we suck at trigonometry so let's use pytouhou for now 291 // we suck at trigonometry so let's use pytouhou for now
120 self._setval(var_id, (self._getval(var_id) + pi) % (2*pi) - pi); 292 self.set_f32(var_id as f32, (self.get_f32(var_id as f32) + std::f32::consts::PI) % (2. * std::f32::consts::PI) - std::f32::consts::PI);
121 } 293 }
122 294
123 // 27(int), 28(float) 295 // 27(int), 28(float)
124 Instruction::Compare(a, b) { 296 SubInstruction::CompareInts(a, b) => {
125 a = self._getval(a); 297 let a = self.get_i32(a);
126 b = self._getval(b); 298 let b = self.get_i32(b);
127 if a < b { 299 if a < b {
128 self.comparison_reg = -1 300 self.comparison_reg = -1;
129 } 301 }
130 else if a == b { 302 else if a == b {
131 self.comparison_reg = 0 303 self.comparison_reg = 0;
132 } 304 }
133 else { 305 else {
134 self.comparison_reg = 1 306 self.comparison_reg = 1;
135 } 307 }
136 } 308 }
137 // 29 309 SubInstruction::CompareFloats(a, b) => {
138 Instruction::RelativeJumpIfLowerThan(frame, ip) { 310 let a = self.get_f32(a);
311 let b = self.get_f32(b);
312 if a < b {
313 self.comparison_reg = -1;
314 }
315 else if a == b {
316 self.comparison_reg = 0;
317 }
318 else {
319 self.comparison_reg = 1;
320 }
321 }
322 // 29
323 SubInstruction::RelativeJumpIfLowerThan(frame, ip) => {
139 if self.comparison_reg == -1 { 324 if self.comparison_reg == -1 {
140 Instruction::RelativeJump(); 325 SubInstruction::RelativeJump(frame, ip);
141 } 326 }
142 } 327 }
143 // 30 328 // 30
144 Instruction::RelativeJumpIfLowerOrEqual(frame, ip) { 329 SubInstruction::RelativeJumpIfLowerOrEqual(frame, ip) => {
145 if self.comparison_reg != 1 { 330 if self.comparison_reg != 1 {
146 Instruction::RelativeJump(); 331 SubInstruction::RelativeJump(frame, ip);
147 } 332 }
148 } 333 }
149 // 31 334 // 31
150 Instruction::RelativeJumpIfEqual(frame, ip) { 335 SubInstruction::RelativeJumpIfEqual(frame, ip) => {
151 if self.comparison_reg == 0 { 336 if self.comparison_reg == 0 {
152 Instruction::RelativeJump(); 337 SubInstruction::RelativeJump(frame, ip);
153 } 338 }
154 } 339 }
155 // 32 340 // 32
156 Instruction::RelativeJumpIfGreaterThan(frame, ip) { 341 SubInstruction::RelativeJumpIfGreaterThan(frame, ip) => {
157 if self.comparison_reg == 1 { 342 if self.comparison_reg == 1 {
158 Instruction::RelativeJump(); 343 SubInstruction::RelativeJump(frame, ip);
159 } 344 }
160 } 345 }
161 // 33 346 // 33
162 Instruction::RelativeJumpIfGreaterOrEqual(frame, ip) { 347 SubInstruction::RelativeJumpIfGreaterOrEqual(frame, ip) => {
163 if self.comparison_reg != -1 348 if self.comparison_reg != -1 {
164 Instruction::RelativeJump(); 349 SubInstruction::RelativeJump(frame, ip);
350 }
165 } 351 }
166 // 34 352 // 34
167 Instruction::RelativeJumpIfNotEqual(frame, ip) { 353 SubInstruction::RelativeJumpIfNotEqual(frame, ip) => {
168 if self.comparison_reg != 0 354 if self.comparison_reg != 0 {
169 Instruction::RelativeJump(); 355 SubInstruction::RelativeJump(frame, ip);
356 }
170 } 357 }
171 // 35 358 // 35
172 Instruction::Call(sub, param1, param2) { 359 SubInstruction::Call(sub, param1, param2) => {
173 // does insane stuff with the stack, not implemented 360 // does insane stuff with the stack, not implemented
174 } 361 unimplemented!()
175 362 }
363
176 // 36 364 // 36
177 Instruction::Ret(frame, ip) { 365 SubInstruction::Return() => {
178 // does insane stuff with the stack, not implemented 366 // does insane stuff with the stack, not implemented
367 unimplemented!()
179 } 368 }
180 // 37 369 // 37
181 Instruction::CallIfSuperior(sub, param1, param2, a, b) { 370 /*
182 if(self._getval(b) <= self._getval(a)) { 371 SubInstruction::CallIfSuperior(sub, param1, param2, a, b) => {
183 Instruction::Call(sub, param1, param2); 372 if self.get_i32(b) <= self.get_i32(a) {
184 } 373 SubInstruction::Call(sub, param1, param2);
185 } 374 }
375 }
376 */
186 // 38 377 // 38
187 Instruction::CallIfSuperiorOrEqual(sub, param1, param2, a, b) { 378 /*
188 if(self._getval(b) <= self._getval(a)) { 379 SubInstruction::CallIfSuperiorOrEqual(sub, param1, param2, a, b) => {
189 Instruction::Call(sub, param1, param2); 380 if self.get_i32(b) <= self.get_i32(a) {
190 } 381 SubInstruction::Call(sub, param1, param2);
191 } 382 }
383 }
384 */
192 // 39 385 // 39
193 Instruction::CallIfEqual(sub, param1, param2, a, b) { 386 SubInstruction::CallIfEqual(sub, param1, param2, a, b) => {
194 if(self._getval(b) == self._getval(a)) { 387 if self.get_i32(b) == self.get_i32(a) {
195 Instruction::Call(sub, param1, param2); 388 SubInstruction::Call(sub, param1, param2);
196 } 389 }
197 } 390 }
198 // 40 391 // 40
199 Instruction::CallIfEqual(sub, param1, param2, a, b) { 392 /*
200 if(self._getval(b) == self._getval(a)) { 393 SubInstruction::CallIfEqual(sub, param1, param2, a, b) => {
201 Instruction::Call(sub, param1, param2); 394 if self.get_i32(b) == self.get_i32(a) {
202 } 395 SubInstruction::Call(sub, param1, param2);
203 } 396 }
204 //41 397 }
205 Instruction::CallIfInferior(sub, param1, param2, a, b) { 398 */
206 if(self._getval(a) < self._getval(b)) { 399 //41
207 Instruction::Call(sub, param1, param2); 400 /*
208 } 401 SubInstruction::CallIfInferior(sub, param1, param2, a, b) => {
209 } 402 if self.get_i32(a) < self.get_i32(b) {
210 //42 403 SubInstruction::Call(sub, param1, param2);
211 Instruction::CallIfInferiorOrEqual(sub, param1, param2, a, b) { 404 }
212 if(self._getval(a) <= self._getval(b)) { 405 }
213 Instruction::Call(sub, param1, param2); 406 */
214 } 407 //42
215 } 408 /*
216 // 43 409 SubInstruction::CallIfInferiorOrEqual(sub, param1, param2, a, b) => {
217 Instruction::SetPos(x, y, z) { 410 if self.get_i32(a) <= self.get_i32(b) {
218 self._enemy.set_pos(self._getval(x), self._getval(y), self._getval(z)); 411 SubInstruction::Call(sub, param1, param2);
219 } 412 }
220 // 44 413 }
221 Instruction::SetPosInterlacing(x, y, z) { 414 */
415 // 43
416 SubInstruction::SetPosition(x, y, z) => {
417 let mut enemy = self.enemy.borrow_mut();
418 enemy.set_pos(self.get_f32(x), self.get_f32(y), self.get_f32(z));
419 }
420 // 44
421 /*
422 SubInstruction::SetPositionInterlacing(x, y, z) => {
222 //TODO: almost the same as setpos, except with 3 different values and sets the 423 //TODO: almost the same as setpos, except with 3 different values and sets the
223 //interlacing, should double check 424 //interlacing, should double check
224 self._enemy.set_pos(self._getval(x), self._getval(y), self._getval(z)); 425 let mut enemy = self.enemy.borrow_mut();
225 } 426 enemy.set_pos(self.get_f32(x), self.get_f32(y), self.get_f32(z));
427 }
428 */
226 // 45 429 // 45
227 Instruction::SetAngleSpeed(angle, speed) { 430 SubInstruction::SetAngleAndSpeed(angle, speed) => {
228 self._enemy.update_mode = 0; 431 let mut enemy = self.enemy.borrow_mut();
229 self._enemy.angle, self._enemy.speed = self._getval(angle), self._getval(speed); 432 enemy.update_mode = 0;
230 } 433 enemy.angle = self.get_f32(angle);
231 // 46 434 enemy.speed = self.get_f32(speed);
232 Instruction::SetRotationSpeed(speed) { 435 }
233 self._enemy.update_mode = 0 436 // 46
234 self._enemy.rotation_speed = self._getval(speed) 437 SubInstruction::SetRotationSpeed(speed) => {
235 } 438 let mut enemy = self.enemy.borrow_mut();
236 // 47 439 enemy.update_mode = 0;
237 Instruction::SetSpeed(speed) { 440 enemy.rotation_speed = self.get_f32(speed);
238 self._enemy.update_mode = 0 441 }
239 self._enemy.speed = self._getval(speed) 442 // 47
240 } 443 SubInstruction::SetSpeed(speed) => {
241 // 48 444 let mut enemy = self.enemy.borrow_mut();
242 Instruction::SetAcceleration(acceleration) { 445 enemy.update_mode = 0;
243 self._enemy.update_mode = 0 446 enemy.speed = self.get_f32(speed);
244 self._enemy.acceleration = self._getval(acceleration) 447 }
448 // 48
449 SubInstruction::SetAcceleration(acceleration) => {
450 let mut enemy = self.enemy.borrow_mut();
451 enemy.update_mode = 0;
452 enemy.acceleration = self.get_f32(acceleration);
245 } 453 }
246 // 49 454 // 49
247 Instruction::SetRandomAngle(min_angle, max_angle) { 455 SubInstruction::SetRandomAngle(min_angle, max_angle) => {
248 angle = self._game.prng.rand_double() * (max_angle - min_angle) + min_angle 456 let angle = self.get_prng().borrow_mut().get_f64() as f32 * (max_angle - min_angle) + min_angle;
249 self._enemy.angle = angle 457 let mut enemy = self.enemy.borrow_mut();
458 enemy.angle = angle;
250 } 459 }
251 460
252 // 83 -> star items >>> life items 461 // 83 -> star items >>> life items
253 462
254 463 _ => unimplemented!()
255 464 }
256 465 }
257 466 }
258
259
260
261
262