128 lines
3.4 KiB
C++
128 lines
3.4 KiB
C++
#include "precompile.h"
|
|
|
|
#include "bullet.h"
|
|
#include "metamgr.h"
|
|
#include "room.h"
|
|
#include "collider.h"
|
|
#include "obstacle.h"
|
|
#include "player.h"
|
|
|
|
Bullet::Bullet():Entity()
|
|
{
|
|
entity_type = ET_Bullet;
|
|
}
|
|
|
|
Bullet::~Bullet()
|
|
{
|
|
}
|
|
|
|
void Bullet::Initialize()
|
|
{
|
|
Entity::Initialize();
|
|
RecalcSelfCollider();
|
|
}
|
|
|
|
void Bullet::Update(int delta_time)
|
|
{
|
|
pos = pos + dir * gun_meta->i->bullet_speed() / 20.0f;
|
|
float distance = (pos - born_pos).Norm();
|
|
if (meta->i->_inventory_slot() == 5 ||
|
|
meta->i->_inventory_slot() == 6) {
|
|
std::vector<Entity*> objects;
|
|
int detection_flags = 0;
|
|
{
|
|
a8::SetBitFlag(detection_flags, ET_Obstacle);
|
|
a8::SetBitFlag(detection_flags, ET_Building);
|
|
}
|
|
room->CollisionDetection(this, detection_flags, objects);
|
|
if (!objects.empty() || distance >= fly_distance) {
|
|
ProcBomb();
|
|
}
|
|
} else {
|
|
std::vector<Entity*> objects;
|
|
int detection_flags = 0;
|
|
{
|
|
a8::SetBitFlag(detection_flags, ET_Obstacle);
|
|
a8::SetBitFlag(detection_flags, ET_Player);
|
|
}
|
|
room->CollisionDetection(this, detection_flags, objects);
|
|
if (!objects.empty() || distance > gun_meta->i->range()) {
|
|
deleted = true;
|
|
if (!objects.empty()) {
|
|
OnHit(objects);
|
|
}
|
|
room->RemoveObjectLater(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Bullet::RecalcSelfCollider()
|
|
{
|
|
if (!self_collider_) {
|
|
self_collider_ = new CircleCollider();
|
|
self_collider_->owner = this;
|
|
colliders.push_back(self_collider_);
|
|
}
|
|
self_collider_->pos = Vector2D();
|
|
self_collider_->rad = gun_meta->i->bullet_rad();
|
|
}
|
|
|
|
void Bullet::OnHit(std::vector<Entity*>& objects)
|
|
{
|
|
for (auto& target : objects) {
|
|
switch (target->entity_type) {
|
|
case ET_Player:
|
|
{
|
|
Human* hum = (Human*)target;
|
|
#if 1
|
|
if (!hum->dead) {
|
|
#else
|
|
if (!hum->dead && (hum->team_id == 0 || hum->team_id != player->team_id)) {
|
|
#endif
|
|
player->stats.damage_amount += 10;
|
|
hum->DecHP(10, player->entity_uniid, player->name);
|
|
}
|
|
}
|
|
break;
|
|
case ET_Obstacle:
|
|
{
|
|
Obstacle* obstacle = (Obstacle*)target;
|
|
if (!obstacle->dead && obstacle->meta->i->attack_type() == 1) {
|
|
obstacle->health = std::max(0.0f, obstacle->health - 10);
|
|
obstacle->dead = obstacle->health <= 0.01f;
|
|
obstacle->dead_frameno = room->frame_no;
|
|
if (obstacle->dead) {
|
|
obstacle->ClearColliders();
|
|
room->ScatterDrop(obstacle->pos, obstacle->meta->i->drop());
|
|
}
|
|
obstacle->BroadcastFullState();
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Bullet::ProcBomb()
|
|
{
|
|
switch (meta->i->_inventory_slot()) {
|
|
case 5:
|
|
{
|
|
//手雷
|
|
Vector2D bomb_pos = pos;
|
|
room->frame_event.AddExplosion(this, meta->i->id(), bomb_pos);
|
|
}
|
|
break;
|
|
case 6:
|
|
{
|
|
//烟雾弹
|
|
Vector2D bomb_pos = pos;
|
|
room->frame_event.AddSmoke(this, meta->i->id(), bomb_pos);
|
|
}
|
|
break;
|
|
}
|
|
room->RemoveObjectLater(this);
|
|
}
|