170 lines
5.5 KiB
C++
170 lines
5.5 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->AddDeletedObject(entity_uniid, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
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());
|
|
}
|
|
room->TouchPlayerList(a8::XParams()
|
|
.SetSender(obstacle),
|
|
[] (Player* hum, a8::XParams& param)
|
|
{
|
|
Obstacle* obstacle = (Obstacle*)param.sender.GetUserData();
|
|
hum->AddToNewObjects(obstacle);
|
|
});
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Bullet::ProcBomb()
|
|
{
|
|
switch (meta->i->_inventory_slot()) {
|
|
case 5:
|
|
{
|
|
//手雷
|
|
::google::protobuf::RepeatedPtrField<::cs::MFExplosion>* explosions = nullptr;
|
|
{
|
|
auto itr = room->frame_data.explosions_hash.find(room->frame_no);
|
|
if (itr == room->frame_data.explosions_hash.end()) {
|
|
room->frame_data.explosions_hash[room->frame_no] = ::google::protobuf::RepeatedPtrField<::cs::MFExplosion>();
|
|
itr = room->frame_data.explosions_hash.find(room->frame_no);
|
|
}
|
|
explosions = &itr->second;
|
|
}
|
|
|
|
#if 1
|
|
Vector2D bomb_pos = pos;
|
|
#else
|
|
float distance = (pos - born_pos).Norm();
|
|
Vector2D bomb_pos = born_pos + born_dir * distance;
|
|
#endif
|
|
cs::MFExplosion* explosion = explosions->Add();
|
|
explosion->set_item_id(meta->i->id());
|
|
bomb_pos.ToPB(explosion->mutable_pos());
|
|
explosion->set_player_id(player->entity_uniid);
|
|
}
|
|
break;
|
|
case 6:
|
|
{
|
|
//烟雾弹
|
|
::google::protobuf::RepeatedPtrField<::cs::MFSmoke>* smokes = nullptr;
|
|
{
|
|
auto itr = room->frame_data.smokes_hash.find(room->frame_no);
|
|
if (itr == room->frame_data.smokes_hash.end()) {
|
|
room->frame_data.smokes_hash[room->frame_no] = ::google::protobuf::RepeatedPtrField<::cs::MFSmoke>();
|
|
itr = room->frame_data.smokes_hash.find(room->frame_no);
|
|
}
|
|
smokes = &itr->second;
|
|
}
|
|
|
|
#if 1
|
|
Vector2D bomb_pos = pos;
|
|
#else
|
|
float distance = (pos - born_pos).Norm();
|
|
Vector2D bomb_pos = born_pos + born_dir * distance;
|
|
#endif
|
|
cs::MFSmoke* smoke = smokes->Add();
|
|
smoke->set_item_id(meta->i->id());
|
|
bomb_pos.ToPB(smoke->mutable_pos());
|
|
smoke->set_player_id(player->entity_uniid);
|
|
}
|
|
break;
|
|
}
|
|
room->AddDeletedObject(entity_uniid, true);
|
|
}
|