aozhiwei 12b963ec79 1
2019-04-02 14:19:40 +08:00

404 lines
12 KiB
C++

#include "precompile.h"
#include <float.h>
#include "playermgr.h"
#include "player.h"
#include "cs_proto.pb.h"
#include "room.h"
#include "metamgr.h"
#include "movement.h"
#include "bullet.h"
#include "obstacle.h"
#include "building.h"
#include "loot.h"
const int F_del_objids = 2;
const int F_full_objects = 3;
const int F_part_objects = 4;
const int F_active_player_id = 5;
const int F_active_player_data = 6;
const int F_alive_count = 15;
const int F_gasT = 16;
const int F_gas_data = 17;
const int F_team_data = 18;
const int F_teams = 19;
const int F_bullets = 20;
const int F_shots = 21;
const int F_explosions = 22;
const int F_emotes = 23;
const int F_ack = 24;
Player::Player()
{
entity_type = ET_Player;
entity_subtype = EST_Player;
update_msg = new cs::SMUpdate();
}
Player::~Player()
{
delete update_msg;
update_msg = nullptr;
}
void Player::Initialize()
{
health = meta->i->health();
helmet = DEF_HELMET_ID;
chest = DEF_CHEST_ID;
#if 1
weapons[GUN_SLOT1].weapon_idx = GUN_SLOT1;
weapons[GUN_SLOT1].weapon_id = DEF_WEAPON_ID;
weapons[GUN_SLOT1].weapon_lv = 1;
weapons[GUN_SLOT1].meta = MetaMgr::Instance()->GetEquip(DEF_WEAPON_ID);;
curr_weapon = &weapons[GUN_SLOT1];
#endif
helmet_meta = MetaMgr::Instance()->GetEquip(helmet);
chest_meta = MetaMgr::Instance()->GetEquip(chest);
RecalcSelfCollider();
inventory.reserve(MAX_INVENTORY_NUM);
for (size_t i = 0; i < inventory.size(); ++i) {
inventory[i] = 0;
}
}
void Player::Update(int delta_time)
{
if (poisoning) {
poisoning_time += delta_time;
}
movement->Update(delta_time);
if (moving) {
UpdateMove();
}
if (room->frame_no % 2 == 0) {
if (shot_start || shot_hold) {
UpdateShot();
}
if (interaction_objids.size() > 0) {
ProcInteraction();
}
if (poisoning) {
UpdatePoisoning();
}
MakeUpdateMsg();
SendNotifyMsg(*update_msg);
{
if (!new_objects.empty()) {
new_objects.clear();
}
}
}
}
void Player::UpdateMove()
{
++moved_frames;
if (moved_frames > 4) {
moving = false;
moved_frames = 0;
return;
}
int speed = std::max(1, (int)GetSpeed());
for (int i = 0; i < speed; ++i) {
Vector2D old_pos = pos;
pos = pos + move_dir;
if (IsCollision()) {
pos = old_pos;
if (i == 0) {
FindPath();
}
break;
}
}
if (last_collision_door && !TestCollision(last_collision_door)) {
last_collision_door = nullptr;
}
}
void Player::UpdateShot()
{
if (shot_start) {
shot_start = false;
Shot();
return;
}
if (shot_hold) {
++series_shot_frames;
if (series_shot_frames > 4) {
shot_hold = false;
series_shot_frames = 0;
Shot();
}
}
}
void Player::Shot()
{
if (!curr_weapon->meta) {
return;
}
{
cs::MFShot* shot = room->frame_data.shots.Add();
shot->set_player_id(entity_uniid);
curr_weapon->ToPB(shot->mutable_weapon());
shot->set_offhand(true);
shot->set_bullskin(10001);
}
{
cs::MFBullet* bullet = room->frame_data.bullets.Add();
bullet->set_player_id(entity_uniid);
bullet->set_bullet_id(curr_weapon->meta->i->use_bullet());
pos.ToPB(bullet->mutable_pos());
attack_dir.ToPB(bullet->mutable_dir());
bullet->set_bulletskin(10001);
bullet->set_gun_id(curr_weapon->meta->i->id());
}
{
Bullet* bullet = new Bullet();
bullet->player = this;
bullet->room = room;
bullet->gun_meta = curr_weapon->meta;
bullet->meta = MetaMgr::Instance()->GetEquip(curr_weapon->meta->i->use_bullet());
bullet->pos = pos;
bullet->dir = attack_dir;
bullet->born_pos = pos;
bullet->born_dir = attack_dir;
bullet->entity_uniid = bullet->room->AllocUniid();
bullet->Initialize();
room->AddBullet(bullet);
}
}
void Player::ProcInteraction()
{
for (auto obj_id : interaction_objids) {
Entity* entity = room->GetEntityByUniId(obj_id);
if (entity) {
switch (entity->entity_type) {
case ET_Obstacle:
{
ObstacleInteraction((Obstacle*)entity);
}
break;
case ET_Loot:
{
LootInteraction((Loot*)entity);
}
break;
default:
break;
}
}
}
interaction_objids.Clear();
}
void Player::ObstacleInteraction(Obstacle* entity)
{
if (entity->is_door) {
if (entity->door_state == DoorStateClose) {
entity->door_state = DoorStateOpen;
entity->pos = Vector2D(entity->building->pos.x + entity->door_state1->x() - entity->building->meta->i->tilewidth() / 2.0,
entity->building->pos.y + entity->door_state1->y() - entity->building->meta->i->tileheight() / 2.0);
} else {
entity->door_state = DoorStateClose;
entity->pos = Vector2D(entity->building->pos.x + entity->door_state0->x() - entity->building->meta->i->tilewidth() / 2.0,
entity->building->pos.y + entity->door_state0->y() - entity->building->meta->i->tileheight() / 2.0);
}
entity->RecalcSelfCollider();
for (auto& pair : room->human_hash_) {
pair.second->new_objects.insert(entity);
pair.second->part_objects.insert(entity);
if (entity->TestCollision(pair.second)) {
pair.second->last_collision_door = entity;
} else if (pair.second->last_collision_door == entity) {
pair.second->last_collision_door = nullptr;
}
}
} else {
}
}
void Player::LootInteraction(Loot* entity)
{
if (entity->pickuped) {
return;
}
entity->pickuped = true;
room->AddDeletedObject(entity->entity_uniid);
}
void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg)
{
bool has_move_dir = msg.has_move_dir();
moving = false;
if (msg.has_move_dir()) {
if (std::abs(msg.move_dir().x()) > FLT_EPSILON ||
std::abs(msg.move_dir().y()) > FLT_EPSILON
) {
move_dir.FromPB(&msg.move_dir());
move_dir.Normalize();
moving = true;
}
}
assert(!isnan(move_dir.x) && !isnan(move_dir.y));
#if 0
moving = msg.has_move_dir();
#endif
if (msg.has_attack_dir()) {
attack_dir.FromPB(&msg.attack_dir());
attack_dir.Normalize();
} else {
if (moving) {
attack_dir = move_dir;
}
}
if (moving) {
moved_frames = 0;
}
shot_start = msg.shot_start();
shot_hold = msg.shot_hold();
if (!shot_hold) {
series_shot_frames = 0;
}
if (msg.has_interaction()) {
interaction_objids = msg.interaction_objids();
}
last_seq_id = msg.seq();
}
void Player::_CMDropItem(f8::MsgHdr& hdr, const cs::CMDropItem& msg)
{
}
void Player::_CMEmote(f8::MsgHdr& hdr, const cs::CMEmote& msg)
{
}
void Player::_CMSpectate(f8::MsgHdr& hdr, const cs::CMSpectate& msg)
{
}
void Player::_CMVoice(f8::MsgHdr& hdr, const cs::CMVoice& msg)
{
cs::SMVoiceNotify notifymsg;
notifymsg.set_mode(msg.mode());
notifymsg.set_account_id(account_id);
notifymsg.set_msg(msg.msg());
auto send_func = [] (Player* hum, a8::XParams& param)
{
cs::SMVoiceNotify* msg = (cs::SMVoiceNotify*)param.sender.GetUserData();
hum->SendNotifyMsg(*msg);
};
room->TouchPlayerList(a8::XParams()
.SetSender(&notifymsg),
send_func);
}
void Player::FillMFActivePlayerData(cs::MFActivePlayerData* player_data)
{
player_data->set_has_action(false);
}
void Player::FillMFGasData(cs::MFGasData* gas_data)
{
gas_data->set_mode(room->gas_data.gas_mode);
if (room->gas_data.gas_mode == GasInactive) {
long long duration = GAS_INACTIVE_TIME * 20 - (room->frame_no - room->gas_data.gas_start_frameno);
gas_data->set_duration(std::max(duration * 50, (long long)1000) / 1000);
} else {
if (room->gas_data.old_area_meta->i->wait_time() <= 0) {
gas_data->set_duration(0);
} else {
long long duration = room->gas_data.old_area_meta->i->wait_time() * 20 -
(room->frame_no - room->gas_data.gas_start_frameno);
gas_data->set_duration(std::max(duration * 50, (long long)1000) / 1000);
}
}
room->gas_data.pos_old.ToPB(gas_data->mutable_pos_old());
room->gas_data.pos_new.ToPB(gas_data->mutable_pos_new());
gas_data->set_rad_old(room->gas_data.rad_old);
gas_data->set_rad_new(room->gas_data.rad_new);
}
void Player::MakeUpdateMsg()
{
update_msg->Clear();
{
update_msg->set_ack(last_seq_id);
for (auto& obj_uniid : room->frame_data.deleted_objects) {
update_msg->add_del_objids(obj_uniid);
}
*update_msg->mutable_shots() = room->frame_data.shots;
*update_msg->mutable_bullets() = room->frame_data.bullets;
for (auto& itr : new_objects) {
itr->FillMFObjectFull(update_msg->add_full_objects());
#if 0
if (itr->frame_data.bullets.size() > 0) {
update_msg->mutable_bullets()->MergeFrom(itr->frame_data.bullets);
}
if (itr->frame_data.shots.size() > 0) {
update_msg->mutable_shots()->MergeFrom(itr->frame_data.shots);
}
#endif
}
for (auto& itr : part_objects) {
itr->FillMFObjectPart(update_msg->add_part_objects());
#if 0
if (itr->frame_data.bullets.size() > 0) {
update_msg->mutable_bullets()->MergeFrom(itr->frame_data.bullets);
}
if (itr->frame_data.shots.size() > 0) {
update_msg->mutable_shots()->MergeFrom(itr->frame_data.shots);
}
#endif
}
if (updated_times == 0) {
update_msg->set_active_player_id(entity_uniid);
FillMFActivePlayerData(update_msg->mutable_active_player_data());
}
if (updated_times == 0 || last_sync_gas_frameno < room->gas_data.gas_start_frameno) {
last_sync_gas_frameno = room->gas_data.gas_start_frameno;
FillMFGasData(update_msg->mutable_gas_data());
}
if (room->gas_data.gas_mode == GasMoving) {
update_msg->set_gas_progress(room->gas_data.gas_progress);
room->gas_data.pos_old.ToPB(update_msg->mutable_gas_pos_old());
}
update_msg->set_alive_count(room->AliveCount());
{
int data_flags32 = 0;
if (!update_msg->del_objids_size() > 0) {
a8::SetBitFlag(data_flags32, F_del_objids);
}
if (!new_objects.empty()) {
a8::SetBitFlag(data_flags32, F_full_objects);
}
if (!part_objects.empty()) {
a8::SetBitFlag(data_flags32, F_part_objects);
}
if (update_msg->bullets_size() > 0) {
a8::SetBitFlag(data_flags32, F_bullets);
}
if (update_msg->shots_size() > 0) {
a8::SetBitFlag(data_flags32, F_shots);
}
if (updated_times == 0) {
a8::SetBitFlag(data_flags32, F_active_player_id);
a8::SetBitFlag(data_flags32, F_active_player_data);
}
a8::SetBitFlag(data_flags32, F_alive_count);
update_msg->set_data_flags32(data_flags32);
}
}
}