2020-09-16 22:44:14 +00:00
|
|
|
use std::borrow::Borrow;
|
2020-08-18 16:46:07 +00:00
|
|
|
|
2020-09-04 23:08:33 +00:00
|
|
|
use crate::caret::CaretType;
|
2020-09-09 13:06:11 +00:00
|
|
|
use crate::common::{Condition, Direction, Flag, Rect};
|
2020-09-16 22:44:14 +00:00
|
|
|
use crate::inventory::{AddExperienceResult, Inventory};
|
2020-09-04 23:08:33 +00:00
|
|
|
use crate::npc::{NPC, NPCMap};
|
2020-09-09 13:06:11 +00:00
|
|
|
use crate::physics::PhysicalEntity;
|
2020-08-18 16:46:07 +00:00
|
|
|
use crate::player::Player;
|
2020-08-19 13:11:34 +00:00
|
|
|
use crate::SharedGameState;
|
2020-08-18 16:46:07 +00:00
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
impl PhysicalEntity for Player {
|
|
|
|
#[inline(always)]
|
|
|
|
fn x(&self) -> isize {
|
|
|
|
self.x
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn y(&self) -> isize {
|
|
|
|
self.y
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn vel_x(&self) -> isize {
|
|
|
|
self.vel_x
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn vel_y(&self) -> isize {
|
|
|
|
self.vel_y
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn size(&self) -> u8 {
|
|
|
|
1
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn hit_bounds(&self) -> &Rect<usize> {
|
|
|
|
&self.hit_bounds
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn set_x(&mut self, x: isize) {
|
|
|
|
self.x = x;
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn set_y(&mut self, y: isize) {
|
|
|
|
self.y = y;
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn set_vel_x(&mut self, vel_x: isize) {
|
|
|
|
self.vel_x = vel_x;
|
|
|
|
}
|
2020-08-18 16:46:07 +00:00
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn set_vel_y(&mut self, vel_y: isize) {
|
|
|
|
self.vel_y = vel_y;
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn cond(&mut self) -> &mut Condition {
|
|
|
|
&mut self.cond
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn flags(&mut self) -> &mut Flag {
|
|
|
|
&mut self.flags
|
|
|
|
}
|
2020-08-18 16:46:07 +00:00
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
#[inline(always)]
|
2020-09-12 21:43:27 +00:00
|
|
|
fn direction(&self) -> Direction {
|
|
|
|
self.direction
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
2020-09-09 13:06:11 +00:00
|
|
|
fn is_player(&self) -> bool {
|
|
|
|
true
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|
2020-09-09 13:06:11 +00:00
|
|
|
}
|
2020-08-20 18:31:47 +00:00
|
|
|
|
2020-09-09 13:06:11 +00:00
|
|
|
impl Player {
|
2020-09-09 16:25:39 +00:00
|
|
|
fn judge_hit_npc_solid_soft(&mut self, npc: &NPC) -> Flag {
|
|
|
|
let mut flags = Flag(0);
|
|
|
|
|
|
|
|
if ((self.y - self.hit_bounds.top as isize) < (npc.y + npc.hit_bounds.bottom as isize - 3 * 0x200))
|
|
|
|
&& ((self.y + self.hit_bounds.top as isize) > (npc.y - npc.hit_bounds.bottom as isize + 3 * 0x200))
|
|
|
|
&& ((self.x - self.hit_bounds.right as isize) < (npc.x + npc.hit_bounds.right as isize))
|
|
|
|
&& ((self.x - self.hit_bounds.right as isize) > npc.x) {
|
|
|
|
if self.vel_x < 0x200 {
|
|
|
|
self.vel_x += 0x200;
|
|
|
|
}
|
|
|
|
|
|
|
|
flags.set_hit_left_wall(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((self.y - self.hit_bounds.top as isize) < (npc.y + npc.hit_bounds.bottom as isize - 3 * 0x200))
|
|
|
|
&& ((self.y + self.hit_bounds.top as isize) > (npc.y - npc.hit_bounds.bottom as isize + 3 * 0x200))
|
|
|
|
&& ((self.x + self.hit_bounds.right as isize - 0x200) > (npc.x - npc.hit_bounds.right as isize))
|
|
|
|
&& ((self.x + self.hit_bounds.right as isize - 0x200) < npc.x) {
|
|
|
|
if self.vel_x > -0x200 {
|
|
|
|
self.vel_x -= 0x200;
|
|
|
|
}
|
|
|
|
|
|
|
|
flags.set_hit_right_wall(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ((self.x - self.hit_bounds.right as isize) < (npc.x + npc.hit_bounds.right as isize - 3 * 0x200))
|
|
|
|
&& ((self.x + self.hit_bounds.right as isize) > (npc.x - npc.hit_bounds.right as isize + 3 * 0x200))
|
|
|
|
&& ((self.y - self.hit_bounds.top as isize) < (npc.y + npc.hit_bounds.bottom as isize))
|
|
|
|
&& ((self.y - self.hit_bounds.top as isize) > npc.y) {
|
|
|
|
if self.vel_y < 0 {
|
|
|
|
self.vel_y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
flags.set_hit_top_wall(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((self.x - self.hit_bounds.right as isize) < (npc.x + npc.hit_bounds.right as isize - 3 * 0x200))
|
|
|
|
&& ((self.x + self.hit_bounds.right as isize) > (npc.x - npc.hit_bounds.right as isize + 3 * 0x200))
|
|
|
|
&& ((self.y + self.hit_bounds.bottom as isize - 0x200) > (npc.y - npc.hit_bounds.top as isize))
|
|
|
|
&& ((self.y + self.hit_bounds.bottom as isize - 0x200) < (npc.y + 3 * 0x200)) {
|
|
|
|
if npc.npc_flags.bouncy() {
|
|
|
|
self.vel_y = npc.vel_y - 0x200;
|
|
|
|
flags.set_hit_bottom_wall(true);
|
|
|
|
} else if !self.flags.hit_bottom_wall() && self.vel_y > npc.vel_y {
|
|
|
|
self.y = npc.y - npc.hit_bounds.top as isize - self.hit_bounds.bottom as isize + 0x200;
|
|
|
|
self.vel_y = npc.vel_y;
|
|
|
|
self.x += npc.vel_x;
|
|
|
|
flags.set_hit_bottom_wall(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
flags
|
|
|
|
}
|
|
|
|
|
2020-09-04 23:08:33 +00:00
|
|
|
fn judge_hit_npc_non_solid(&mut self, npc: &NPC) -> Flag {
|
|
|
|
let mut flags = Flag(0);
|
|
|
|
let hit_left = if npc.direction == Direction::Left { npc.hit_bounds.left } else { npc.hit_bounds.right } as isize;
|
|
|
|
let hit_right = if npc.direction == Direction::Left { npc.hit_bounds.right } else { npc.hit_bounds.left } as isize;
|
|
|
|
|
|
|
|
if self.x + (2 * 0x200) > npc.x - hit_left
|
|
|
|
&& self.x - (2 * 0x200) < npc.x + hit_right
|
|
|
|
&& self.y + (2 * 0x200) > npc.y - npc.hit_bounds.top as isize
|
|
|
|
&& self.y - (2 * 0x200) < npc.y + npc.hit_bounds.bottom as isize {
|
|
|
|
flags.set_hit_left_wall(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
flags
|
|
|
|
}
|
|
|
|
|
2020-09-12 23:45:36 +00:00
|
|
|
pub fn tick_npc_collisions(&mut self, state: &mut SharedGameState, npc_map: &mut NPCMap, inventory: &mut Inventory) {
|
2020-09-04 23:08:33 +00:00
|
|
|
for npc_id in npc_map.npc_ids.iter() {
|
2020-09-12 04:43:29 +00:00
|
|
|
if let Some(npc_cell) = npc_map.npcs.get(npc_id) {
|
2020-09-12 23:45:36 +00:00
|
|
|
let mut npc = npc_cell.borrow_mut();
|
2020-09-04 23:08:33 +00:00
|
|
|
if !npc.cond.alive() { continue; }
|
|
|
|
|
|
|
|
let mut flags = Flag(0);
|
|
|
|
|
|
|
|
if npc.npc_flags.solid_soft() {
|
2020-09-12 04:43:29 +00:00
|
|
|
flags = self.judge_hit_npc_solid_soft(npc.borrow());
|
2020-09-09 16:25:39 +00:00
|
|
|
self.flags.0 |= flags.0;
|
2020-09-04 23:08:33 +00:00
|
|
|
} else if npc.npc_flags.solid_hard() {
|
|
|
|
//
|
|
|
|
} else {
|
2020-09-12 04:43:29 +00:00
|
|
|
flags = self.judge_hit_npc_non_solid(npc.borrow());
|
2020-09-04 23:08:33 +00:00
|
|
|
}
|
|
|
|
|
2020-09-12 23:45:36 +00:00
|
|
|
// xp pickup
|
|
|
|
if flags.0 != 0 && npc.npc_type == 1 {
|
2020-09-16 22:44:14 +00:00
|
|
|
state.sound_manager.play_sfx(14);
|
2020-09-12 23:45:36 +00:00
|
|
|
match inventory.add_xp(npc.exp, state) {
|
2020-09-16 22:44:14 +00:00
|
|
|
AddExperienceResult::None => {}
|
2020-09-12 23:45:36 +00:00
|
|
|
AddExperienceResult::LevelUp => {
|
2020-09-16 22:44:14 +00:00
|
|
|
state.sound_manager.play_sfx(27);
|
2020-09-12 23:45:36 +00:00
|
|
|
state.create_caret(self.x, self.y, CaretType::LevelUp, Direction::Left);
|
2020-09-16 22:44:14 +00:00
|
|
|
}
|
2020-09-12 23:45:36 +00:00
|
|
|
AddExperienceResult::AddStar => {
|
|
|
|
if self.equip.has_whimsical_star() && self.stars < 3 {
|
|
|
|
self.stars += 1;
|
|
|
|
}
|
2020-09-16 22:44:14 +00:00
|
|
|
}
|
2020-09-12 23:45:36 +00:00
|
|
|
}
|
|
|
|
npc.cond.set_alive(false);
|
|
|
|
}
|
|
|
|
|
2020-09-10 23:41:00 +00:00
|
|
|
if npc.npc_flags.interactable() && !state.control_flags.interactions_disabled() && flags.0 != 0 && self.cond.interacted() {
|
2020-09-04 23:08:33 +00:00
|
|
|
state.textscript_vm.start_script(npc.event_num);
|
|
|
|
self.cond.set_interacted(false);
|
|
|
|
self.vel_x = 0;
|
|
|
|
self.question = false;
|
|
|
|
}
|
2020-09-06 00:37:42 +00:00
|
|
|
|
2020-09-10 23:41:00 +00:00
|
|
|
if npc.npc_flags.event_when_touched() && !state.control_flags.interactions_disabled() && flags.0 != 0 {
|
2020-09-06 00:37:42 +00:00
|
|
|
state.textscript_vm.start_script(npc.event_num);
|
|
|
|
}
|
2020-09-09 16:25:39 +00:00
|
|
|
|
|
|
|
if state.control_flags.control_enabled() && !npc.npc_flags.interactable() {
|
2020-09-10 23:41:00 +00:00
|
|
|
if flags.0 != 0 && npc.damage != 0 && !state.control_flags.interactions_disabled() {
|
2020-09-09 16:25:39 +00:00
|
|
|
self.damage(npc.damage as isize, state);
|
|
|
|
}
|
|
|
|
}
|
2020-09-04 23:08:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-20 18:31:47 +00:00
|
|
|
if self.question {
|
|
|
|
state.create_caret(self.x, self.y, CaretType::QuestionMark, Direction::Left);
|
|
|
|
}
|
|
|
|
}
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|