1
2026-08-16 11:26:48
发布于:浙江
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <algorithm>
#include <limits>
#include <stdexcept>
#include <cctype>
#include <cmath>
#include <Windows.h>
#include <fstream>
#include <conio.h>
// 文字颜色
void SetColor(int textColor, int bgColor) {
WORD color = (bgColor << 4) + textColor;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}
void ShowCombatText(const stdstring& text, int color)
{
SetColor(color, 0);
stdcout << text;
SetColor(7, 0);
}
// 游戏状态枚举
enum class GameState {
MAIN_MENU, EXPLORING, COMBAT, GAME_OVER, VICTORY, EVACUATION, SHOP
};
//难度选择
enum class Difficulty
{
NORMAL, //常规:难度低,爆率低
SECRET, //机密:一般难度,中等爆率
TOP_SECRET //绝密:高难度,高爆率
};
//全局当前难度
Difficulty current_difficulty = Difficulty::NORMAL;
//地区枚举 8个区域
enum class AreaId
{
CORE, //核心区(唯一有撤离点)
NUCLEAR_PLANT, //核电站
ADMIN_BUILD, //行政楼
MEDICAL_CENTER, //医疗中心
MILITARY_CAMP, //军营
RESIDENTIAL, //居民区
INDUSTRIAL, //工业区
HARBOUR //港口
};
// 物品类型枚举
enum class ItemType {
CONSUMABLE, WEAPON, ARMOR_HEAD, ARMOR_BODY, BACKPACK, COLLECTIBLE, AMMO
};
// 武器/弹药类型枚举
enum class WeaponType {
KNIFE, PISTOL, RIFLE, SPECIAL
};
enum class AmmoType {
PISTOL, RIFLE, SPECIAL
};
// 容器类型枚举
enum class ContainerType {
SAFE, SMALL_SAFE, WEAPON_BOX, PARCEL, SUITCASE, STORAGE_BOX, CLOTHING, MANHOLE, SCATTERED, MEDICAL_BOX,
STORAGE_BOX_S
};
// 基础物品结构体
struct Item {
stdstring name;
stdstring description;
ItemType type;
int value;
int size;
Item(const stdstring& n, const stdstring& desc, ItemType t, int v = 0, int s = 1)
: name(n), description(desc), type(t), value(v), size(s) {}
virtual ~Item() {}
};
// 消耗品
struct Consumable : Item {
int health_restore;
int status_effect; // 扩展:状态效果(0=无,1=临时防御,2=临时暴击)
Consumable(const stdstring& n, const stdstring& desc, int hr, int se = 0, int v = 0, int s = 1)
: Item(n, desc, ItemTypeCONSUMABLE, v, s), health_restore(hr), status_effect(se) {}
};
// 弹药
struct Ammo : Item {
AmmoType ammo_type;
int quantity;
Ammo(const stdstring& n, const stdstring& desc, AmmoType at, int qty, int v = 0, int s = 1)
: Item(n, desc, ItemTypeAMMO, v, s), ammo_type(at), quantity(qty) {}
};
// 武器
struct Weapon : Item {
int damage;
int crit_rate;
int hit_rate; //新增:武器命中率 0~100
WeaponType weapon_type;
AmmoType ammo_type;
int current_ammo;
int max_ammo;
Weapon(const std::string& n, const std::string& desc, int d, int cr, int hr, WeaponType wt, AmmoType at,
int max_am, int v = 0, int s = 3)
: Item(n, desc, ItemType::WEAPON, v, s),
damage(d), crit_rate(cr), hit_rate(hr), //初始化命中率
weapon_type(wt), ammo_type(at),
current_ammo(max_am), max_ammo(max_am) {}
};
// 头部防具
struct HeadArmor : Item {
int defense;
int dodge_rate;
int damage_reduction;
HeadArmor(const stdstring& n, const stdstring& desc, int def, int dr, int dmg_red = 0,
int v = 0, int s = 2)
: Item(n, desc, ItemType::ARMOR_HEAD, v, s),
defense(def), dodge_rate(dr), damage_reduction(dmg_red) {}
};
// 身体防具
struct BodyArmor : Item {
int defense;
int dodge_rate;
int damage_reduction;
BodyArmor(const stdstring& n, const stdstring& desc, int def, int dr, int dmg_red = 0,
int v = 0, int s = 3)
: Item(n, desc, ItemType::ARMOR_BODY, v, s),
defense(def), dodge_rate(dr), damage_reduction(dmg_red) {}
};
// 背包
struct Backpack : Item {
int capacity;
Backpack(const stdstring& n, const stdstring& desc, int cap, int v = 0, int s = 5)
: Item(n, desc, ItemType::BACKPACK, v, s), capacity(cap) {}
};
// 容器
struct Container {
ContainerType type;
stdstring name;
stdvector<Item*> contents; // 初始物品
std::vector<Item*> uncollected_items; // 未拾取的物品
bool is_opened; // 是否已打开(但可能还有未拾取物品)
bool safe_unlocked; //新增:大保险箱是否已经解开摩斯密码
Container(ContainerType t, const std::string& n, const std::vector<Item*>& c)
: type(t), name(n), contents(c), uncollected_items(), is_opened(false), safe_unlocked(false) {}
~Container() {
for (Item* item : contents) delete item;
for (Item* item : uncollected_items) delete item;
}
// 判断容器是否还有未拾取的物品
bool has_uncollected() const {
return !uncollected_items.empty();
}
};
//区域配置:名字、描述、本区域最大本地步数、相邻地区、容器权重、精英敌人倍率
struct AreaConfig
{
AreaId id;
stdstring name;
stdstring desc;
int max_local_step; //在本区域最多走多少步,之后必须切换相邻地区
std::vector<AreaId> neighbor; //相邻可前往的地区
//容器权重,总和1000,create_container根据权重随机
int weight_safe; //保险箱
int weight_small_safe; //小保险箱
int weight_weaponbox; //装备补给箱
int weight_medical; //医疗箱
int weight_parcel; //快递包裹
int weight_suitcase; //旅行箱
int weight_storage; //收纳盒
int weight_cloth; //衣服堆
int weight_manhole; //井盖
int weight_scatter; //散落物
int weight_storage_s; //高级储物箱
float elite_enemy_mult; //精英敌人概率倍率
};
// 敌人
struct Enemy {
stdstring name;
int health;
int max_health;
int damage;
int defense;
int exp_reward;
int money_reward;
stdvector<Item*> equipment;
stdvector<Item*> drop_items;
stdvector<Item*> rare_drops;
bool is_strong;
Enemy(const std::string& n, int h, int d, int def, int exp, int money,
const std::vector<Item*>& eq, const std::vector<Item*>& drops, const std::vector<Item*>& rare = {}, bool strong = false)
: name(n), health(h), max_health(h), damage(d), defense(def),
exp_reward(exp), money_reward(money), equipment(eq), drop_items(drops),
rare_drops(rare), is_strong(strong) {}
~Enemy() {
for (Item* item : equipment) delete item;
for (Item* item : drop_items) delete item;
for (Item* item : rare_drops) delete item;
}
void take_damage(int dmg, int crit_rate, int textColor = 12) {
bool is_crit = (rand() % 100) < crit_rate;
int actual_dmg = is_crit ? dmg * 2 : dmg;
actual_dmg = std::max(0, actual_dmg - defense);
health = std::max(0, health - actual_dmg);
std::string msg;
if(is_crit)
{
msg = "暴击!你对 " + name + " 造成了 " + std::to_string(actual_dmg) + " 点伤害!\n";
}
else
{
msg = "你对 " + name + " 造成了 " + std::to_string(actual_dmg) + " 点伤害!\n";
}
ShowCombatText(msg, textColor);
}
};
// 友军
struct BotPlayer {
std::string name;
int health;
int max_health;
int damage;
int alive_chance;
bool is_alive;
BotPlayer(const std::string& n, int h, int d, int chance)
: name(n), health(h), max_health(h), damage(d), alive_chance(chance), is_alive(false) {}
void attack(Enemy* enemy) {
if (!is_alive || !enemy) return;
if (rand() % 100 < 70) {
int actual_damage = (rand() % 100 < 15) ? damage * 2 : damage;
actual_damage = std::max(0, actual_damage - enemy->defense);
enemy->health = std::max(0, enemy->health - actual_damage);
std::cout << "\n友军 " << name << " 对 " << enemy->name << " 造成了 " << actual_damage
<< (actual_damage > damage ? " 点暴击伤害!" : " 点伤害!") << std::endl;
} else {
std::cout << "\n友军 " << name << " 的攻击被 " << enemy->name << " 躲开了!" << std::endl;
}
}
void take_damage(int dmg) {
health = std::max(0, health - dmg);
if (health == 0) {
is_alive = false;
std::cout << "友军 " << name << " 被击倒了!" << std::endl;
} else {
std::cout << "友军 " << name << " 受到了 " << dmg << " 点伤害!" << std::endl;
}
}
void reset() {
is_alive = (rand() % 100) < alive_chance;
if (is_alive) {
health = max_health;
std::cout << "友军 " << name << " 加入了你的队伍!" << std::endl;
}
}
};
void auto_equip_if_slot_empty(Item* item);
// 玩家
struct Player {
stdstring name;
int health;
int max_health;
Weapon* main_weapon;
Weapon* secondary_weapon;
Weapon* pistol_weapon;
Weapon* knife_weapon;
HeadArmor* equipped_head;
BodyArmor* equipped_body;
Backpack* equipped_backpack;
stdvector<Item*> inventory;
std::vector<Item*> temp_cache;
const int CACHE_MAX_SLOT = 10;
int current_load;
int level;
int exp;
int money;
int kill_count;
int collectibles_value;
bool reached_evac;
int temp_defense; // 临时防御加成
int temp_crit; // 临时暴击加成
Player(const std::string& n)
: name(n), health(10000000), max_health(10000000),
main_weapon(nullptr), secondary_weapon(nullptr), pistol_weapon(nullptr), knife_weapon(nullptr),
equipped_head(nullptr), equipped_body(nullptr), equipped_backpack(nullptr),
current_load(0), level(1000000), exp(1000000), money(2000000000), kill_count(0),
collectibles_value(0), reached_evac(false), temp_defense(0), temp_crit(0) {
// 初始装备
knife_weapon = new Weapon("初始的刀", "基础攻击武器,暴击率极高", 15000, 50, 70,
WeaponType::KNIFE, AmmoType::SPECIAL, 0, 30000);
equipped_backpack = new Backpack("基础背包", "标准军用背包", 12000, 10000);
add_item(new Consumable("急救包", "恢复30点生命值", 3000000, 0, 5000));
}
~Player() {
delete main_weapon;
delete secondary_weapon;
delete pistol_weapon;
delete knife_weapon;
delete equipped_head;
delete equipped_body;
delete equipped_backpack;
for (Item* item : inventory) delete item;
for(Item* item : temp_cache) delete item;
temp_cache.clear();
}
int get_total_capacity() {
return equipped_backpack ? equipped_backpack->capacity : 5;
}
// 移除武器数量限制,改为可替换
bool can_add_weapon(Weapon* weapon) {
return true; // 允许拾取任意数量武器,装备时进行替换
}
// 检查是否能添加物品
bool can_add_item(Item* item) {
// 武器不再有数量限制,只检查背包空间
if (item->type == ItemType::WEAPON) {
return (current_load + item->size) <= get_total_capacity();
}
// 防具无数量限制且不占空间
if (item->type == ItemType::ARMOR_HEAD || item->type == ItemType::ARMOR_BODY) {
return true;
}
// 其他物品计算空间
return (current_load + item->size) <= get_total_capacity();
}
void take_damage(int dmg) {
// 计算总防御(头部+身体+临时防御)
int total_defense = temp_defense;
if (equipped_head) total_defense += equipped_head->defense;
if (equipped_body) total_defense += equipped_body->defense;
// 计算总闪避率(头部+身体)
int total_dodge = 0;
if (equipped_head) total_dodge += equipped_head->dodge_rate;
if (equipped_body) total_dodge += equipped_body->dodge_rate;
// 计算总减伤
int total_reduction = 0;
if (equipped_head) total_reduction += equipped_head->damage_reduction;
if (equipped_body) total_reduction += equipped_body->damage_reduction;
total_reduction = std::min(90, total_reduction); // 最大减伤90%
// 闪避判定
if ((rand() % 100) < total_dodge) {
std::cout << "你成功闪避了攻击!\n";
return;
}
// 伤害计算(先减防再减伤)
int actual_dmg = std::max(0, dmg - total_defense);
actual_dmg = actual_dmg * (100 - total_reduction) / 100;
actual_dmg = std::max(1, actual_dmg); // 至少造成1点伤害
health -= actual_dmg;
if (health < 0) health = 0;
ShowCombatText("你受到了 " + std::to_string(actual_dmg) + " 点伤害!\n",12);
// 临时状态重置(受伤后清除临时加成)
temp_defense = 0;
temp_crit = 0;
}
void heal(int amount) {
health += amount;
if (health > max_health) health = max_health;
ShowCombatText("你恢复了 " + std::to_string(amount) + " 点生命值!\n",10);
}
// 查找并使用弹药
bool reload_weapon(Weapon* weapon) {
if (!weapon || weapon->weapon_type == WeaponType::KNIFE) {
std::cout << "该武器不需要弹药!\n";
return false;
}
for (size_t i = 0; i < inventory.size(); ++i) {
if (inventory[i]->type == ItemType::AMMO) {
Ammo* ammo = dynamic_cast<Ammo*>(inventory[i]);
if (ammo && ammo->ammo_type == weapon->ammo_type) {
int needed = weapon->max_ammo - weapon->current_ammo;
if (needed <= 0) {
std::cout << "武器弹药已满,无需装填!\n";
return true;
}
int use = std::min(needed, ammo->quantity);
weapon->current_ammo += use;
ammo->quantity -= use;
std::cout << "你为 " << weapon->name << " 装填了 " << use << " 发子弹。\n";
if (ammo->quantity <= 0) {
remove_item(ammo);
delete ammo;
}
return true;
}
}
}
std::cout << "没有找到适用的弹药!\n";
return false;
}
// 添加物品时不再限制武器数量
bool add_item(Item* item) {
if (!can_add_item(item)) {
return false;
}
inventory.push_back(item);
// 消耗品、变卖物、弹药和武器都计算负载
if (item->type != ItemType::ARMOR_HEAD && item->type != ItemType::ARMOR_BODY) {
current_load += item->size;
}
// 如果是变卖物,更新总价值
if (item->type == ItemType::COLLECTIBLE) {
collectibles_value += item->value;
}
Sleep(500);
if (item->type == ItemType::COLLECTIBLE && item->value > 1000000) Sleep(1500);
else if (item->type == ItemType::COLLECTIBLE && item->value >= 100000) Sleep(1000);
else if (item->type == ItemType::COLLECTIBLE && item->value > 240000) Sleep(500);
else if (item->type == ItemType::COLLECTIBLE && item->value > 5000) Sleep(200);
else if (item->type == ItemType::COLLECTIBLE && item->value > 1000) Sleep(50);
Sleep(rand()%300);
std::cout << "你获得了: ";
if (item->type == ItemType::COLLECTIBLE && item->value > 240000) SetColor(4,0);
else if (item->type == ItemType::COLLECTIBLE && item->value > 50000) SetColor(6,0);
else if (item->type == ItemType::COLLECTIBLE && item->value > 10000) SetColor(5,0);
else if (item->type == ItemType::COLLECTIBLE && item->value > 5000) SetColor(3,0);
else if (item->type == ItemType::COLLECTIBLE && item->value > 1000) SetColor(10,0);
else if (item->type == ItemType::COLLECTIBLE && item->value <= 1000) SetColor(8,0);
std::cout << item->name;
SetColor(7,0);
std::cout << " (价值: " << item->value;
if (item->type != ItemType::ARMOR_HEAD && item->type != ItemType::ARMOR_BODY) {
std::cout << ", 大小: " << item->size;
}
if (item->type == ItemType::AMMO) {
Ammo* ammo = dynamic_cast<Ammo*>(item);
if (ammo) { // 安全检查
std::cout << ", 数量: " << ammo->quantity;
}
}
std::cout << ")\n";
// 高价值物品特殊提示
if (item->type == ItemType::COLLECTIBLE && item->value > 240000) {
if (item->name == "非洲之心") {
SetColor(4,0);
std::cout << "========================================\n";
std::cout << "!!! 惊人发现 !!!\n";
std::cout << item->name << " 价值连城,足以改变战局!\n";
std::cout << "世界上最大的钻石,璀璨夺目,象征永恒的爱!\n";
std::cout << "========================================\n";
SetColor(7,0);
}
else if (item->name == "海洋之泪") {
SetColor(4,0);
std::cout << "========================================\n";
std::cout << "!!! 惊人发现 !!!\n";
std::cout << item->name << " 价值连城,足以改变战局!\n";
std::cout << "浑然天成,珠圆玉润的巨大天然珍珠,其通体散发镭射光泽,令人目眩神迷!\n";
std::cout << "========================================\n";
SetColor(7,0);
}
else {
std::cout << "========================================\n";
std::cout << "!!! 重大发现 !!!\n";
SetColor(4,0);
std::cout << item->name;
SetColor(7,0);
std::cout << " 价值连城,足以改变战局!\n立即前往撤离点,这将是历史性的收获!\n";
std::cout << "========================================\n";
}
}
//====新增:加入背包成功后,槽位为空自动装备====
auto_equip_if_slot_empty(item);
return true;
}
void remove_item(Item* item) {
auto it = std::find(inventory.begin(), inventory.end(), item);
if (it != inventory.end()) {
// 消耗品、变卖物、弹药和武器都计算负载
if (item->type != ItemType::ARMOR_HEAD && item->type != ItemType::ARMOR_BODY) {
current_load -= item->size;
}
if (item->type == ItemType::COLLECTIBLE) {
collectibles_value -= item->value;
}
inventory.erase(it);
}
}
// 武器装备改为替换制,支持任意武器替换已装备武器
// 武器装备改为替换制,支持任意武器替换已装备武器
void equip_weapon(Weapon* weapon) {
if (!weapon) return; // 空指针安全检查
// 先将当前装备的同类型武器放回背包(如果是同类武器)
Weapon* old_weapon = nullptr;
// 根据武器类型决定替换哪个装备位
if (weapon->weapon_type == WeaponType::PISTOL) {
old_weapon = pistol_weapon;
pistol_weapon = weapon;
} else if (weapon->weapon_type == WeaponType::KNIFE) {
old_weapon = knife_weapon;
knife_weapon = weapon;
} else if (weapon->weapon_type == WeaponType::RIFLE || weapon->weapon_type == WeaponType::SPECIAL) {
// =========【修改点:有空槽自动填充,无空槽才弹窗】=========
if (main_weapon == nullptr)
{
//主武器槽空,直接装主武器
old_weapon = nullptr;
main_weapon = weapon;
}
else if (secondary_weapon == nullptr)
{
//副武器槽空,直接装副武器
old_weapon = nullptr;
secondary_weapon = weapon;
}
else
{
//两个槽都满了,才弹出选择菜单
std::cout << "选择要替换的装备位:\n";
std::cout << "1. 主武器 (" << (main_weapon ? main_weapon->name : "无") << ")\n";
std::cout << "2. 副武器 (" << (secondary_weapon ? secondary_weapon->name : "无") << ")\n";
std::cout << "请选择: ";
int choice;
std::cin >> choice;
if (choice == 1) {
old_weapon = main_weapon;
main_weapon = weapon;
} else {
old_weapon = secondary_weapon;
secondary_weapon = weapon;
}
}
}
// 从背包移除新装备的武器(如果存在)
remove_item(weapon);
// 将旧武器添加到背包(如果存在)
if (old_weapon) {
std::cout << "你卸下了 " << old_weapon->name << "\n";
add_item(old_weapon);
}
std::cout << "你装备了 " << weapon->name << " (伤害: " << weapon->damage
<< ", 暴击率: " << (weapon->crit_rate + temp_crit) << "%, 弹药: " << weapon->current_ammo << "/" << weapon->max_ammo << ")\n";
}
void equip_head(HeadArmor* head) {
if (!head) return; // 空指针安全检查
HeadArmor* old_head = equipped_head;
equipped_head = head;
// 从背包移除新装备的防具
remove_item(head);
// 将旧防具添加到背包(如果存在)
if (old_head) {
std::cout << "你卸下了 " << old_head->name << "\n";
add_item(old_head);
}
std::cout << "你装备了 " << head->name << " (防御: " << head->defense
<< ", 闪避率: " << head->dodge_rate << "%, 减伤: " << head->damage_reduction << "%)\n";
}
void equip_body(BodyArmor* body) {
if (!body) return; // 空指针安全检查
BodyArmor* old_body = equipped_body;
equipped_body = body;
// 从背包移除新装备的防具
remove_item(body);
// 将旧防具添加到背包(如果存在)
if (old_body) {
std::cout << "你卸下了 " << old_body->name << "\n";
add_item(old_body);
}
std::cout << "你装备了 " << body->name << " (防御: " << body->defense
<< ", 闪避率: " << body->dodge_rate << "%, 减伤: " << body->damage_reduction << "%)\n";
}
void equip_backpack(Backpack* backpack) {
if (!backpack) return; // 空指针安全检查
Backpack* old_backpack = equipped_backpack;
// 检查新背包是否能容纳当前物品
if (backpack->capacity < current_load) {
std::cout << "新背包容量不足,无法装备!请先整理物品。\n";
return;
}
equipped_backpack = backpack;
// 从背包移除新装备的背包
remove_item(backpack);
// 将旧背包添加到背包(如果存在)
if (old_backpack) {
std::cout << "你卸下了 " << old_backpack->name << " (容量: " << old_backpack->capacity << ")\n";
add_item(old_backpack);
}
std::cout << "你装备了 " << backpack->name << " (容量: " << backpack->capacity << ")\n";
}
void gain_exp(int amount) {
exp += amount;
std::cout << "你获得了 " << amount << " 点经验值!\n";
while (exp >= level * 100) {
exp -= level * 100;
level++;
max_health += 20;
health = max_health;
std::cout << "恭喜你升到 " << level << " 级!生命值提升至 " << max_health << "!\n";
}
}
//缓存是否还有空位
bool cache_has_space() const
{
return (int)temp_cache.size() < CACHE_MAX_SLOT;
}
//将背包内物品移入临时缓存
bool move_item_to_cache(Item* item)
{
if(!item || !cache_has_space()) return false;
//不允许把正在装备的东西丢进缓存
if ((item->type == ItemType::WEAPON &&
(item == main_weapon || item == secondary_weapon ||
item == pistol_weapon || item == knife_weapon)) ||
(item->type == ItemType::ARMOR_HEAD && item == equipped_head) ||
(item->type == ItemType::ARMOR_BODY && item == equipped_body) ||
(item->type == ItemType::BACKPACK && item == equipped_backpack))
{
return false;
}
auto it = std::find(inventory.begin(), inventory.end(), item);
if(it == inventory.end()) return false;
//从背包移除,不delete,负载要扣掉
if (item->type != ItemType::ARMOR_HEAD && item->type != ItemType::ARMOR_BODY)
{
current_load -= item->size;
}
if(item->type == ItemType::COLLECTIBLE)
{
collectibles_value -= item->value;
}
inventory.erase(it);
temp_cache.push_back(item);
return true;
}
//把缓存物品移回背包,失败返回false(背包满)
bool move_item_from_cache_to_inventory(Item* item)
{
if(!item) return false;
auto it = std::find(temp_cache.begin(), temp_cache.end(), item);
if(it == temp_cache.end()) return false;
//复用can_add_item判断背包能不能装下
if(!can_add_item(item))
{
return false;
}
temp_cache.erase(it);
inventory.push_back(item);
//增加负载
if (item->type != ItemType::ARMOR_HEAD && item->type != ItemType::ARMOR_BODY)
{
current_load += item->size;
}
if(item->type == ItemType::COLLECTIBLE)
{
collectibles_value += item->value;
}
//自动装备逻辑,移回背包触发
auto_equip_if_slot_empty(item);
return true;
}
//清空缓存(本局结束调用,物品全部释放销毁,缓存撤离/死亡直接消失)
void clear_temp_cache()
{
for(auto p : temp_cache) delete p;
temp_cache.clear();
}
// 变卖物品功能(现在在商店中使用)
void sell_item(Item* item) {
if (!item) return; // 空指针安全检查
int sell_gain = static_cast<int>(std::round(item->value * 0.9f));
money += sell_gain;
std::cout << "你卖掉了 " << item->name << ",获得了 " << sell_gain << " 金钱!(黑市折价90%)\n";
remove_item(item);
delete item;
}
void drop_item(Item* item) {
if (!item) return; // 空指针安全检查
// 不能丢弃当前装备
if ((item->type == ItemType::WEAPON &&
(item == main_weapon || item == secondary_weapon ||
item == pistol_weapon || item == knife_weapon)) ||
(item->type == ItemType::ARMOR_HEAD && item == equipped_head) ||
(item->type == ItemType::ARMOR_BODY && item == equipped_body) ||
(item->type == ItemType::BACKPACK && item == equipped_backpack)) {
std::cout << "不能丢弃正在装备的物品,请先卸下!\n";
return;
}
std::cout << "你丢弃了 " << item->name << "\n";
remove_item(item);
delete item;
}
// 使用消耗品(支持状态效果)
void use_consumable(Consumable* consumable) {
if (!consumable) return; // 空指针安全检查
heal(consumable->health_restore);
if (consumable->status_effect == 1) {
temp_defense += 5;
std::cout << "你获得了临时防御加成(+5)!\n";
} else if (consumable->status_effect == 2) {
temp_crit += 10;
std::cout << "你获得了临时暴击加成(+10%)!\n";
}
remove_item(consumable);
delete consumable;
}
};
struct RedVault
{
std::vector<Item*> stored_red_collectibles;
long long bank_money;
long long total_kills;
bool unlock_blood_blade;
bool unlock_bi_xiao;
//====新增:玩家大厅选择的开局近战武器,-1=自动(旧逻辑)====
int starter_melee_choice;
RedVault() : bank_money(0), total_kills(0), unlock_blood_blade(false), unlock_bi_xiao(false), starter_melee_choice(-1) {}
//从加载仓库
void load_from_file(const std::string& filename)
{
//先清空旧内存
for(auto p : stored_red_collectibles) delete p;
stored_red_collectibles.clear();
bank_money = 0;
total_kills = 0;
unlock_blood_blade = false;
unlock_bi_xiao = false;
starter_melee_choice = -1; //初始化!
std::ifstream fin(filename, std::ios::binary);
if(!fin.is_open()) return;
fin.read((char*)&bank_money, sizeof(long long));
fin.read((char*)&total_kills, sizeof(long long));
fin.read((char*)&unlock_blood_blade, sizeof(bool));
fin.read((char*)&unlock_bi_xiao, sizeof(bool));
//====修复:不要写red_vault.,直接访问成员====
fin.read((char*)&starter_melee_choice, sizeof(int));
size_t count;
fin.read((char*)&count, sizeof(size_t));
for(size_t i=0;i<count;i++)
{
std::string name,desc;
long long val;
int sz;
{
uint32_t len;
fin.read((char*)&len,4);
name.resize(len);
fin.read(&name[0],len);
}
{
uint32_t len;
fin.read((char*)&len,4);
desc.resize(len);
fin.read(&desc[0],len);
}
fin.read((char*)&val,sizeof(long long));
fin.read((char*)&sz,sizeof(int));
stored_red_collectibles.push_back(new Item(name,desc,ItemType::COLLECTIBLE,(int)val,sz));
}
bank_money = 900000000000000000LL;
fin.close();
}
//保存仓库到
void save_to_file(const std::string& filename)
{
std::ofstream fout(filename, std::ios::binary);
fout.write((char*)&bank_money, sizeof(long long));
fout.write((char*)&total_kills, sizeof(long long));
fout.write((char*)&unlock_blood_blade, sizeof(bool));
fout.write((char*)&unlock_bi_xiao, sizeof(bool));
//修复,去掉red_vault.
fout.write((char*)&starter_melee_choice, sizeof(int));
size_t count = stored_red_collectibles.size();
fout.write((char*)&count, sizeof(size_t));
for(auto item : stored_red_collectibles)
{
uint32_t len = (uint32_t)item->name.size();
fout.write((char*)&len,4);
fout.write(item->name.c_str(), len);
len = (uint32_t)item->description.size();
fout.write((char*)&len,4);
fout.write(item->description.c_str(), len);
long long val = item->value;
fout.write((char*)&val,sizeof(long long));
fout.write((char*)&item->size,sizeof(int));
}
bank_money = 900000000000000000LL;
fout.close();
}
//释放内存
~RedVault()
{
for(auto p : stored_red_collectibles) delete p;
}
};
RedVault red_vault;
const stdstring VAULT_FILE = "red_vault.bin";
// 全局变量
bool player_last_attack_melee = false;
GameState current_state;
AreaId current_area; // 当前所在地区
int global_step = 0; //全局总步数(商店触发使用)
int local_step = 0; //当前区域本地步数
Player player("默认士兵");
stdvector<BotPlayer> bots; // 人机玩家列表
Enemy* current_enemy = nullptr;
stdvector<Item*> loot_items; // 战利品列表
Container* current_container = nullptr;
int explore_steps = 0; // 探索步数,用于触发撤离点和商店
stdvector<Item*> shop_items; // 商店商品
stdvector<Item*> lobby_starting_gifts;
bool in_hidden_mission_combat = false; // 萨萨隐藏任务战斗:禁止逃跑
//全局区域表
stdvector<AreaConfig> area_table = {
{
AreaIdCORE, "核心区", "任务核心区域,高概率出现撤离点",
35,
{AreaIdNUCLEAR_PLANT, AreaIdADMIN_BUILD, AreaIdRESIDENTIAL},
80,60,100,80,120,110,100,90,80,100,80,
1.0f
},
{
AreaIdNUCLEAR_PLANT,"核电站","辐射笼罩,高价值物资多,精英敌人频繁",
28,
{AreaIdCORE,AreaIdINDUSTRIAL},
150,120,80,50,60,50,90,30,120,100,150,
1.8f
},
{
AreaIdADMIN_BUILD,"行政楼","大量保险柜,文件与贵重物品",
32,
{AreaIdCORE,AreaIdMEDICAL_CENTER},
180,160,70,60,100,120,110,40,40,80,40,
1.2f
},
{
AreaIdMEDICAL_CENTER,"医疗中心","大量医疗物资,精英敌人较少",
30,
{AreaIdADMIN_BUILD,AreaIdRESIDENTIAL},
40,30,50,300,100,90,80,70,60,120,60,
0.7f
},
{
AreaIdMILITARY_CAMP,"军营","武器补给箱极多,危险,大量精英",
26,
{AreaIdINDUSTRIAL,AreaIdHARBOUR},
50,40,280,40,60,40,70,30,50,80,100,
2.0f
},
{
AreaIdRESIDENTIAL,"居民区","居民私人物品,包裹旅行箱多,相对安全",
40,
{AreaIdCORE,AreaIdMEDICAL_CENTER,AreaIdHARBOUR},
40,50,40,100,180,170,120,140,80,100,80,
0.6f
},
{
AreaIdINDUSTRIAL,"工业区","废弃工厂,井盖散落物多",
33,
{AreaIdNUCLEAR_PLANT,AreaIdMILITARY_CAMP},
60,50,130,40,80,70,110,50,160,150,100,
1.4f
},
{
AreaIdHARBOUR,"港口","大量集装箱,高级储物箱、包裹",
36,
{AreaIdMILITARY_CAMP,AreaIdRESIDENTIAL},
90,70,110,60,160,130,120,60,70,90,170,
1.1f
}
};
// 函数声明
void lobby_select_melee(); //大厅选择开局近战武器
void cleanup_game_session();
bool meet_sasa_event = false;
void lobby_shop();
void event_explorer_sasa();
void game_loop();
void show_main_menu();
void handle_main_menu_input();
void start_game();
void explore();
void handle_explore_input();
void encounter_enemy();
void generate_enemy();
void combat();
void handle_combat_input();
bool attempt_escape();
void game_over(bool victory);
void clear_screen();
void press_any_key();
void manage_inventory();
void loot_corpse();
void show_stats();
void generate_container();
void open_container();
void create_collectibles(std::vector<Item*>& items, int count, ContainerType container_type);
void evacuation_point();
void reset_bots();
void show_shop();
void handle_shop_input();
void generate_shop_items();
void enemy_attack();
void enemy_defeated();
void string_input_to_digit(int& choice);
long long get_red_vault_total_value(); //新增
bool safe_morse_unlock();
void event_sasa_hidden_mission();
std::string morse_encode(int num)
{
switch(num)
{
case 0: return "-----";
case 1: return ".----";
case 2: return "..---";
case 3: return "...--";
case 4: return "....-";
case 5: return ".....";
case 6: return "-....";
case 7: return "--...";
case 8: return "---..";
case 9: return "----.";
default: return "";
}
}
// 大保险箱数字密码解锁交互;返回true=解锁成功,false=放弃打开保险箱
bool safe_morse_unlock(){
// 生成4位随机密码数字
int pass[5];
for(int i=0;i<4;i++){
pass[i] = rand()%10;
}
// 如果在此之前有使用 cin >> 操作,缓冲区会残留 '\n',这里一次性清除
stdcin.ignore(stdnumeric_limitsstd::streamsizemax(), '\n');
while(true) //无限重试,不会损坏箱子物品
{
clear_screen();
SetColor(14,0);
stdcout << "==================== 大保险箱密码锁 ====================\n";
SetColor(7,0);
stdcout << "保险箱的密码以摩斯密码形式展示,请解读摩斯码,输入4位数字密码\n";
stdcout << "--------------------------------------------------------\n";
stdcout << "【摩斯密码提示】\n";
stdcout << "0:----- 1:.---- 2:..--- 3:...-- 4:....-\n";
stdcout << "5:..... 6:-.... 7:--... 8:---.. 9:----.\n";
stdcout << "--------------------------------------------------------\n";
stdcout << "保险箱摩斯密码:";
for(int i=0;i<4;i++)
{
stdcout << morse_encode(pass[i]) << " ";
}
stdcout << "\n\n";
stdcout << "说明:输入4个数字,中间用空格隔开。\n";
stdcout << "示例输入:1 2 3 4\n";
stdcout << "输入 q 可以放弃解锁,关闭保险箱\n";
stdcout << "请输入密码:";
stdstring line;
// getline 会读取整行包括最后的换行符并丢弃它,缓冲区变空,下次循环直接等待新输入
stdgetline(stdcin, line);
//放弃解锁
if(line == "q" || line == "Q")
{
stdcout << "\n你放弃解锁保险箱。\n";
press_any_key();
return false;
}
//分割输入为4段
stdvectorstd::string parts;
stdstring cur="";
for(char ch : line)
{
if(ch == ' '){
if(!cur.empty()){
parts.push_back(cur);
cur.clear();
}
}else{
cur.push_back(ch);
}
}
if(!cur.empty()) parts.push_back(cur);
if(parts.size() !=4 )
{
SetColor(12,0);
stdcout << "\n格式错误!必须输入4位数字!\n";
SetColor(7,0);
press_any_key();
continue;
}
bool ok = true;
for(int i=0;i<4;i++)
{
int num;
try
{
num = std::stoi(parts[i]);
}
catch(...)
{
ok = false;
break;
}
// 注意:这里逻辑有点小问题,如果 num != pass[i] 应该立即失败,但 num<0||num>9 检查是多余的因为 stoi 转换成功通常是数字,除非有前导符号等,但为了安全保留
if(num <0 || num>9)
{
ok = false;
break;
}
if(num != pass[i])
{
ok = false;
break;
}
}
if(ok)
{
SetColor(10,0);
std::cout << "\n密码正确!保险箱锁芯转动,锁成功解锁!\n";
SetColor(7,0);
press_any_key();
return true;
}
else
{
SetColor(12,0);
std::cout << "\n密码错误!锁没有打开,请重新尝试!(不限次数)\n";
SetColor(7,0);
press_any_key();
//循环回去继续输入,物品不会损坏,箱子完好
}
}
}
void lobby_select_melee()
{
clear_screen();
stdcout << "===== 选择下一局开局近战武器 =====\n";
stdcout << "当前选择:";
if(red_vault.starter_melee_choice == -1)
{
stdcout << "【自动】根据仓库价值与解锁自动分配\n";
}
else if(red_vault.starter_melee_choice == 0) stdcout << "黑刃";
else if(red_vault.starter_melee_choice == 1) stdcout << "金刚";
else if(red_vault.starter_melee_choice == 2) stdcout << "裂空者";
else if(red_vault.starter_melee_choice == 3) stdcout << "灰海";
else if(red_vault.starter_melee_choice == 4) stdcout << "血痕【已解锁】";
else if(red_vault.starter_melee_choice == 5) stdcout << "碧霄【已解锁】";
stdcout << "\n\n";
std::cout << "可选择列表:\n";
std::cout << "-1. 【自动】沿用旧逻辑,按仓库价值自动选刀\n";
std::cout << "0. 黑刃 | 默认初始刀\n";
std::cout << "1. 金刚 | 钢制指虎(仓库价值≥1000万解锁)\n";
std::cout << "2. 裂空者 | 弹簧刀(仓库价值≥1亿解锁)\n";
std::cout << "3. 灰海 | 战术手斧(仓库价值≥5亿解锁)\n";
std::cout << "4. 血痕 | 杀戮利刃(累计击杀250解锁)" << (red_vault.unlock_blood_blade?"":"【未解锁】") << "\n";
std::cout << "5. 碧霄 | 让颠覆开始吧!(萨萨隐藏任务解锁)" << (red_vault.unlock_bi_xiao?"":"【未解锁】") << "\n";
std::cout << "\n输入编号选择,输入0返回主菜单:";
int sel;
string_input_to_digit(sel);
if(sel == 0)
{
return;
}
//校验是否可以选择该武器
bool ok = true;
long long vault_val = get_red_vault_total_value();
if(sel == 1 && vault_val < 10000000) ok = false;
if(sel == 2 && vault_val < 100000000) ok = false;
if(sel == 3 && vault_val < 500000000) ok = false;
if(sel == 4 && !red_vault.unlock_blood_blade) ok = false;
if(sel == 5 && !red_vault.unlock_bi_xiao) ok = false;
if(!ok)
{
std::cout << "\n该武器尚未解锁,无法选择!\n";
press_any_key();
return;
}
if(sel < -1 || sel >5)
{
std::cout << "\n无效编号!\n";
press_any_key();
return;
}
red_vault.starter_melee_choice = sel;
red_vault.save_to_file(VAULT_FILE);
std::cout << "\n设置成功!下一局游戏将使用该开局近战武器。\n";
press_any_key();
}
// 新增:当对应装备槽为空时自动装备;槽位已有装备则不处理
void auto_equip_if_slot_empty(Item* item)
{
if (!item) return;
if(item->type == ItemType::WEAPON)
{
Weapon* w = dynamic_cast<Weapon*>(item);
if(!w) return;
if(w->weapon_type == WeaponType::PISTOL)
{
if(player.pistol_weapon == nullptr)
{
player.equip_weapon(w);
}
}
else if(w->weapon_type == WeaponType::KNIFE)
{
if(player.knife_weapon == nullptr)
{
player.equip_weapon(w);
}
}
else if(w->weapon_type == WeaponType::RIFLE || w->weapon_type == WeaponType::SPECIAL)
{
//主武器空就装主武器,否则副武器空就装副武器;两个都满就不自动装备
if(player.main_weapon == nullptr)
{
player.equip_weapon(w);
}
else if(player.secondary_weapon == nullptr)
{
player.equip_weapon(w);
}
//两个槽都有武器,不自动装备
}
}
else if(item->type == ItemType::ARMOR_HEAD)
{
HeadArmor* h = dynamic_cast<HeadArmor*>(item);
if(h && player.equipped_head == nullptr)
{
player.equip_head(h);
}
}
else if(item->type == ItemType::ARMOR_BODY)
{
BodyArmor* b = dynamic_cast<BodyArmor*>(item);
if(b && player.equipped_body == nullptr)
{
player.equip_body(b);
}
}
}
// 主游戏循环
void game_loop() {
player.level = 1000;
player.exp = 9999999;
player.money = 2000000000;
red_vault.bank_money = 900000000000000000LL;
while (current_state != GameStateGAME_OVER && current_state != GameStateVICTORY) {
clear_screen();
switch (current_state) {
case GameStateMAIN_MENU:
show_main_menu();
handle_main_menu_input();
break;
case GameStateEXPLORING:
explore();
handle_explore_input();
break;
case GameStateCOMBAT:
combat();
handle_combat_input();
break;
case GameStateEVACUATION:
evacuation_point();
break;
case GameStateSHOP:
show_shop();
handle_shop_input();
break;
default:
current_state = GameStateGAME_OVER;
break;
}
}
clear_screen();
show_stats(); // 显示统计信息
if (current_state == GameStateVICTORY) {
game_over(true);
} else {
game_over(false);
}
}
AreaConfig* get_area_config(AreaId aid)
{
for(auto &ac : area_table)
{
if(ac.id == aid) return ∾
}
return nullptr;
}
//当local_step >=本区域max_local_step,调用这个函数,选择前往相邻地区
void area_jump_menu()
{
clear_screen();
AreaConfig* cfg = get_area_config(current_area);
stdcout << "=本区域已经探索充分=\n";
std::cout << "当前位置:" << cfg->name << "|本地步数已达上限" << cfg->max_local_step << "\n\n";
// 自动随机挑选一个相邻区域,玩家不能选择
size_t rand_idx = rand() % cfg->neighbor.size();
current_area = cfg->neighbor[rand_idx];
local_step = 0;
AreaConfig* newcfg = get_area_config(current_area);
std::cout << "\n你来到了【" << newcfg->name << "】:" << newcfg->desc << "\n";
press_any_key();
}
// 主菜单
void show_main_menu() {
std::cout << "===== ";
SetColor(6,0);
std::cout << "三角粥行动-1.4";
SetColor(7,0);
std::cout << " =====\n";
std::cout << "1. 开始新游戏\n";
std::cout << "2. 查看红色品质仓库\n";
std::cout << "3. 大厅商店(仓库金钱)\n";
std::cout << "4. 修改游戏难度\n";
std::cout << "5. 选择开局近战武器\n"; //新增
std::cout << "6. 退出游戏\n";
std::cout << "==============================\n";
//显示当前难度
std::cout << "当前难度:";
if(current_difficulty == Difficulty::NORMAL) SetColor(10,0),std::cout<<"常规(简单,低爆率)";
else if(current_difficulty == Difficulty::SECRET) SetColor(14,0),std::cout<<"机密(普通,中等爆率)";
else if(current_difficulty == Difficulty::TOP_SECRET) SetColor(4,0),std::cout<<"绝密(困难,高爆率)";
SetColor(7,0);
std::cout << "\n仓库总金钱:" << red_vault.bank_money << "\n"; //显示仓库金钱
}
void lobby_shop()
{
clear_screen();
// 合并对局黑市全部商品池到大厅商店
std::vector<Item*> shop_pool = {
// =消耗品=
new Consumable("高级急救包", "恢复50点生命值", 50, 0, 50000, 2),
new Consumable("止痛药", "恢复20点生命值并获得临时防御", 20, 1, 10000, 1),
new Consumable("肾上腺素", "恢复10点生命值并获得临时暴击", 10, 2, 12000, 1),
new Consumable("绷带", "恢复15点生命值", 15, 0, 8000, 1),
new Consumable("医疗喷雾", "恢复40点生命值", 40, 0, 45000, 1),
// ===弹药===
new Ammo("手枪子弹(大量)", "适用于大多数手枪", AmmoType::PISTOL, 50, 2000, 2),
new Ammo("步枪子弹(大量)", "适用于大多数步枪", AmmoType::RIFLE, 50, 3000, 3),
new Ammo("特殊弹药", "适用于特殊武器", AmmoType::SPECIAL, 20, 5000, 2),
new Ammo("狙击专用弹药", "高精度狙击弹", AmmoType::RIFLE, 20, 8000, 2),
// ===防具===
new HeadArmor("轻型头盔", "基础头部防护", 3, 5, 2, 50000, 2),
new BodyArmor("轻型防弹衣", "基础身体防护", 8, 3, 5, 100000, 4),
new HeadArmor("重型头盔", "强大的头部防护", 5, 0, 5, 100000, 3),
new BodyArmor("重型防弹衣", "强大的身体防护", 12, 0, 10, 200000, 6),
new HeadArmor("战术头盔", "战术头部防护", 4, 4, 2, 80000, 3),
new BodyArmor("战术防弹衣", "战术身体防护", 9, 3, 7, 170000, 5),
new HeadArmor("特种头盔", "凯夫拉纤维制成", 4, 4, 15, 150000, 3),
new BodyArmor("特种防弹衣", "凯夫拉纤维制成", 10, 3, 25, 250000, 5),
// ===背包===
new Backpack("中型背包", "容量更大的背包", 18, 50000, 4),
new Backpack("大型背包", "容量超大的背包", 25, 100000, 6),
new Backpack("巨型背包", "人体最大承载量!", 30, 250000, 8),
// ====== 原装备补给箱全部武器加入大厅商店 ======
new Weapon("QBZ-95步枪", "国产突击步枪", 23, 30, 70, WeaponType::RIFLE, AmmoType::RIFLE, 30, 50000, 3),
new Weapon("AKM步枪", "经典步枪", 25, 35, 70, WeaponType::RIFLE, AmmoType::RIFLE, 30, 90000, 3),
new Weapon("M9手枪", "军用手枪", 15, 10, 70, WeaponType::PISTOL, AmmoType::PISTOL, 15, 40000, 2),
new Weapon("MP5冲锋枪", "小型冲锋枪", 18, 20, 70, WeaponType::RIFLE, AmmoType::RIFLE, 30, 75000, 3),
new Weapon("MGL榴弹发射器", "特殊武器", 35, 15, 60, WeaponType::SPECIAL, AmmoType::SPECIAL, 6, 120000, 4),
new Weapon("M4A1步枪", "高精度步枪", 23, 25, 80, WeaponType::RIFLE, AmmoType::RIFLE, 30, 80000, 3),
new Weapon("SCAR-L步枪", "模块化步枪", 24, 24, 70, WeaponType::RIFLE, AmmoType::RIFLE, 32, 90000, 3),
new Weapon("AWP狙击枪", "大威力狙击枪", 75, 0, 70, WeaponType::RIFLE, AmmoType::RIFLE, 5, 600000, 5),
new Weapon("UMP45冲锋枪", ".45口径冲锋枪", 18, 30, 70, WeaponType::RIFLE, AmmoType::RIFLE, 30, 130000, 3),
new Weapon("M14步枪", "半自动步枪", 29, 25, 65, WeaponType::RIFLE, AmmoType::RIFLE, 36, 280000, 3),
new Weapon("G36C步枪", "紧凑型步枪", 22, 22, 70, WeaponType::RIFLE, AmmoType::RIFLE, 30, 150000, 3),
new Weapon("FAMAS步枪", "法国突击步枪", 25, 20, 70, WeaponType::RIFLE, AmmoType::RIFLE, 35, 160000, 3),
new Weapon("P90冲锋枪", "单兵自卫武器", 27, 25, 70, WeaponType::RIFLE, AmmoType::RIFLE, 50, 60000, 3),
new Weapon("Desert Eagle手枪", "大威力手枪", 23, 15, 70, WeaponType::PISTOL, AmmoType::PISTOL, 7, 80000, 2),
new Weapon("SVD狙击枪", "半自动狙击枪", 40, 12, 70, WeaponType::RIFLE, AmmoType::RIFLE, 15, 250000, 4),
new Weapon("M249轻机枪", "班用机枪", 23, 20, 70, WeaponType::RIFLE, AmmoType::RIFLE, 100, 300000, 5),
new Weapon("Kar98k步枪", "栓动步枪", 45, 15, 70, WeaponType::RIFLE, AmmoType::RIFLE, 5, 200000, 3),
new Weapon("FS12霰弹枪", "半自动霰弹枪", 25, 65, 70, WeaponType::RIFLE, AmmoType::RIFLE, 15, 550000, 4),
new Weapon("K416步枪", "可靠的步枪", 28, 28, 70, WeaponType::RIFLE, AmmoType::RIFLE, 38, 100000, 3),
new Weapon("M250轻机枪", "轻机枪", 35, 25, 70, WeaponType::RIFLE, AmmoType::RIFLE, 65, 200000, 5),
new Weapon("ASH步枪", "高威力突击步枪", 32, 20, 70, WeaponType::RIFLE, AmmoType::RIFLE, 30, 110000, 3),
new Weapon("M7步枪", "高威力突击步枪", 30, 25, 70, WeaponType::RIFLE, AmmoType::RIFLE, 45, 150000, 3),
};
while(true)
{
clear_screen();
std::cout << "=====大厅商店【仓库金钱】=====\n";
std::cout << "你的仓库金钱:" << red_vault.bank_money << "\n";
std::cout << "购买的物品将在下一局开局放入你的背包!\n\n";
for(size_t i=0;i<shop_pool.size();i++)
{
auto p = shop_pool[i];
std::cout << i+1 << ". "<< p->name << " |价值:" << p->value << "\n";
}
std::cout << "\n0.离开商店\n请选择:";
int sel;
string_input_to_digit(sel);
if(sel ==0) break;
sel -=1;
if(sel <0 || sel >= (int)shop_pool.size())
{
std::cout << "无效选择\n";
press_any_key();
continue;
}
Item* src = shop_pool[sel];
if(red_vault.bank_money < src->value)
{
std::cout << "仓库金钱不足!\n";
press_any_key();
continue;
}
//复制物品,存入开局礼物池
Item* new_item = nullptr;
if(auto c = dynamic_cast<Consumable*>(src))
{
new_item = new Consumable(c->name,c->description,c->health_restore,c->status_effect,c->value,c->size);
}
else if(auto w = dynamic_cast<Weapon*>(src))
{
new_item = new Weapon(w->name,w->description,w->damage,w->crit_rate,w->hit_rate,
w->weapon_type,w->ammo_type,w->max_ammo,w->value,w->size);
}
else if(auto h = dynamic_cast<HeadArmor*>(src))
{
new_item = new HeadArmor(h->name,h->description,h->defense,h->dodge_rate,h->damage_reduction,h->value,h->size);
}
else if(auto b = dynamic_cast<BodyArmor*>(src))
{
new_item = new BodyArmor(b->name,b->description,b->defense,b->dodge_rate,b->damage_reduction,b->value,b->size);
}
else if(auto bp = dynamic_cast<Backpack*>(src))
{
new_item = new Backpack(bp->name,bp->description,bp->capacity,bp->value,bp->size);
}
else if(auto a = dynamic_cast<Ammo*>(src))
{
new_item = new Ammo(a->name,a->description,a->ammo_type,a->quantity,a->value,a->size);
}
if(!new_item)
{
std::cout << "复制物品失败\n";
press_any_key();
continue;
}
red_vault.bank_money -= src->value;
lobby_starting_gifts.push_back(new_item);
red_vault.save_to_file(VAULT_FILE);
std::cout << "成功购买!下一局开局获得:" << new_item->name << "\n";
press_any_key();
}
//清理模板池
for(auto p:shop_pool) delete p;
press_any_key();
}
Weapon* create_starter_melee_weapon();
void cleanup_game_session()
{
//释放当前敌人
delete current_enemy;
current_enemy = nullptr;
//释放容器
delete current_container;
current_container = nullptr;
//清理loot_items
for(auto p : loot_items) delete p;
loot_items.clear();
//清理商店物品
for(auto p : shop_items) delete p;
shop_items.clear();
//bots只是vector,不需要delete,clear即可
bots.clear();
//====新增:大厅开局礼物池清理,防止内存泄漏====
for(auto p : lobby_starting_gifts) delete p;
lobby_starting_gifts.clear();
// =========重置全局player(全局对象不能delete,手动释放内部资源,重建初始装备)=========
//释放player内部所有武器防具背包
delete player.main_weapon;
delete player.secondary_weapon;
delete player.pistol_weapon;
delete player.knife_weapon;
delete player.equipped_head;
delete player.equipped_body;
delete player.equipped_backpack;
//清空背包
for(auto p : player.inventory) delete p;
player.inventory.clear();
player.current_load = 0;
//重置玩家基础数值
player.name = "默认士兵";
player.health = 10000000;
player.max_health = 10000000;
player.exp = 1000000;
player.level = 1000000;
player.money = 2000000000;
player.kill_count = 0;
player.collectibles_value = 0;
player.reached_evac = false;
player.temp_defense = 0;
player.temp_crit = 0;
//========改动:调用函数动态生成开局近战武器========
player.knife_weapon = create_starter_melee_weapon();
player.equipped_backpack = new Backpack("基础背包", "标准军用背包", 120000, 5000);
player.add_item(new Consumable("急救包", "恢复30点生命值", 300000, 0, 5000));
global_step =0;
local_step =0;
current_area = AreaId::CORE;
meet_sasa_event = false;
player.clear_temp_cache();
}
void string_input_to_digit(int& choice) {
for(;;)
{
stdstring input;
stdcout << "请输入你的选择: ";
stdcin.clear();
if (!(stdcin >> input))
{
stdcin.ignore(stdnumeric_limitsstd::streamsizemax(), '\n');
stdcout << "输入异常,请重试。\n";
system("pause");
continue;
}
bool all_digit = true;
for (char ch : input)
{
if (!std::isdigit(static_cast<unsigned char>(ch)))
{
all_digit = false;
break;
}
}
if (!all_digit) {
std::cout << "无效的输入,请重试。\n";
system("pause");
continue;
} else {
try
{
choice = stoi(input);
}
catch(...)
{
std::cout << "数字过大或者格式错误,请重试。\n";
system("pause");
continue;
}
break;
}
}
}
// 根据红色仓库计算总价值
long long get_red_vault_total_value()
{
long long sum = 0;
for(auto item : red_vault.stored_red_collectibles)
{
sum += item->value;
}
return sum;
}
// 根据仓库总价值,获取开局近战武器
Weapon* create_starter_melee_weapon()
{
//玩家手动选择优先
int choice = red_vault.starter_melee_choice;
if(choice != -1)
{
switch(choice)
{
case 0:
return new Weapon("黑刃", "基础攻击武器,暴击率中等", 150000, 400000, 100,
WeaponTypeKNIFE, AmmoTypeSPECIAL, 0, 30000);
case 1:
return new Weapon("金刚","钢制指虎,增加拳头杀伤,均衡伤害暴击",180000,500000, 100,
WeaponTypeKNIFE, AmmoTypeSPECIAL,0,30000);
case 2:
return new Weapon("裂空者","锋利的弹簧折叠刀,极高暴击",220000,6500000, 100,
WeaponTypeKNIFE, AmmoTypeSPECIAL,0,30000);
case 3:
return new Weapon("灰海","战术手斧,高伤害重型近战武器,破坏力惊人", 280000, 550000, 100,
WeaponTypeKNIFE, AmmoTypeSPECIAL, 0, 30000);
case 4:
return new Weapon("血痕","浸染无数敌人鲜血的利刃,杀戮铸就的凶器", 240000, 600000, 100,
WeaponTypeKNIFE, AmmoTypeSPECIAL, 0, 30000);
case 5:
return new Weapon("碧霄","让颠覆开始吧!",280000,700000,100,
WeaponTypeKNIFE,AmmoTypeSPECIAL,0,30000);
default:
//异常,fallback走自动
break;
}
}
//==== choice=-1,执行原来自动逻辑 ====
long long vault_val = get_red_vault_total_value();
if(red_vault.unlock_bi_xiao)
{
return new Weapon("碧霄","让颠覆开始吧!",280000,700000,100,
WeaponType::KNIFE,AmmoType::SPECIAL,0,30000);
}
if(red_vault.unlock_blood_blade)
{
return new Weapon("血痕","浸染无数敌人鲜血的利刃,杀戮铸就的凶器", 240000, 600000, 100,
WeaponType::KNIFE, AmmoType::SPECIAL, 0, 30000);
}
if(vault_val >= 500000000)
{
return new Weapon("灰海","战术手斧,高伤害重型近战武器,破坏力惊人", 280000, 550000, 100,
WeaponType::KNIFE, AmmoType::SPECIAL, 0, 30000);
}
else if(vault_val >= 100000000)
{
return new Weapon("裂空者","锋利的弹簧折叠刀,极高暴击",220000,6500000, 100,
WeaponType::KNIFE, AmmoType::SPECIAL,0,30000);
}
else if(vault_val >= 10000000)
{
return new Weapon("金刚","钢制指虎,增加拳头杀伤,均衡伤害暴击",180000,500000, 100,
WeaponType::KNIFE, AmmoType::SPECIAL,0,30000);
}
else
{
return new Weapon("黑刃", "基础攻击武器,暴击率中等", 150000, 400000, 100,
WeaponType::KNIFE, AmmoType::SPECIAL, 0, 30000);
}
}
全部评论 1
//判断是否红色品质变卖物(>240000为红色)
bool is_red_collectible(Item* item)
{
if(!item) return false;
return item->type == ItemTypeCOLLECTIBLE && item->value > 240000;
}
//打印仓库内容
void show_red_vault()
{
clear_screen();
stdcout << "=红色品质仓库=\n";
stdcout << "仓库总金钱:" << red_vault.bank_money << "\n\n";
if(red_vault.stored_red_collectibles.empty())
{
stdcout << "仓库为空,还没有存入红色变卖物\n";
}
else
{
long long total_val = 0;
for(size_t i =0;i<red_vault.stored_red_collectibles.size();i++)
{
auto it = red_vault.stored_red_collectibles[i];
SetColor(4,0);
stdcout << i+1 <<". "<< it->name << " |价值:" << it->value << "\n";
SetColor(7,0);
total_val += it->value;
}
stdcout << "\n仓库物品总价值:" << total_val << "\n";
}
stdcout << "\n操作:\n";
stdcout << "输入序号出售该红色物品(90%折价);0 返回\n";
stdcout << "请输入:";
int opt;
string_input_to_digit(opt);
if(opt ==0)
{
return;
}
opt -=1;
if(opt >=0 && opt < (int)red_vault.stored_red_collectibles.size())
{
Item* item = red_vault.stored_red_collectibles[opt];
long long sell_price = (long long)stdround(item->value * 0.9f);
red_vault.bank_money += sell_price;
stdcout << "出售【" << item->name << "】获得仓库金钱:" << sell_price << "\n";
delete item;
red_vault.stored_red_collectibles.erase(red_vault.stored_red_collectibles.begin()+opt);
red_vault.save_to_file(VAULT_FILE);
}
else
{
stdcout << "无效序号\n";
}
press_any_key();
}3天前 来自 浙江
0//把玩家背包中变卖物处理:红色存入仓库;非红色变卖物自动换成仓库金钱;其他物品直接丢弃
void store_player_red_to_vault()
{
stdvector<Item*> keep;
for(auto item : player.inventory)
{
if(item->type == ItemTypeCOLLECTIBLE)
{
if(is_red_collectible(item))
{
//红色品质存入仓库
red_vault.stored_red_collectibles.push_back(new Item(*item));
delete item;
}
else
{
//新增:非红色变卖物,直接出售,钱进仓库总金钱(黑市90%折价)
long long sell_val = (long long)stdround(item->value * 0.9f);
red_vault.bank_money += sell_val;
delete item;
}
}
else
{
//武器/防具/消耗品/弹药全部丢弃,不保留
delete item;
}
}
player.inventory.swap(keep);
//重置玩家背包负载、变卖物价值
player.current_load = 0;
player.collectibles_value = 0;
red_vault.save_to_file(VAULT_FILE);
}
void change_difficulty()
{
clear_screen();
stdcout << "=选择游戏难度=\n";
stdcout << "1. 常规:敌人弱,物资爆率低,适合新手\n";
stdcout << "2. 机密:敌人属性中等,物资爆率中等\n";
stdcout << "3. 绝密:敌人强力,精英更多,物资爆率大幅提高!\n";
stdcout << "请选择难度:";
int sel;
string_input_to_digit(sel);
if(sel ==1)
{
current_difficulty = DifficultyNORMAL;
stdcout<<"已切换为【常规】难度\n";
}
else if(sel ==2)
{
current_difficulty = DifficultySECRET;
stdcout<<"已切换为【机密】难度\n";
}
else if(sel ==3)
{
current_difficulty = DifficultyTOP_SECRET;
stdcout<<"已切换为【绝密】难度\n";
}
else
{
std::cout<<"无效选择,难度不变\n";
}
press_any_key();
}
void handle_main_menu_input() {
int choice;
string_input_to_digit(choice);
switch (choice) {
case 1:
start_game();
break;
//新增查看仓库分支
case 2:
show_red_vault();
break;
case 3:
lobby_shop(); //新增大厅商店函数调用
break;
case 4:
change_d3天前 来自 浙江
0ifficulty(); //修改难度
break;
case 5:
lobby_select_melee();
break;
case 6:
red_vault.save_to_file(VAULT_FILE);
cleanup_game_session();
clear_screen();
stdcout << "正在退出游戏...\n";
Sleep(600);
stdcout << "退出成功!\n";
exit(EXIT_SUCCESS);
default:
stdcout << "无效的输入,请重试。\n";
press_any_key();
break;
}
}
// 开始新游戏
void start_game() {
stdcout << "请输入你的士兵代号: ";
stdcin >> player.name;
//修复:清除cin异常标记,再丢弃缓冲区剩余字符,防止卡死
stdcin.clear();
stdcin.ignore(stdnumeric_limitsstd::streamsize::max(), '\n');//==== 注意!这里删除原来那一大段delete武器、清空背包代码!cleanup_game_session已经处理完!==== player.health = player.max_health; player.exp = 0; player.level = 1; player.money = 0; player.kill_count = 0; player.collectibles_value = 0; player.reached_evac = false; player.temp_defense = 0; player.temp_crit = 0; current_area = AreaId::CORE; global_step = 0; local_step = 0; meet_sasa_event = false; // 初始化人机玩家 bots.clear(); bots.emplace_back("侦察兵甲", 60, 12, 30); // 30%概率出现 bots.emplace_back("突击手乙", 80, 15, 25); // 25%概率出现 bots.emplace_back("医疗兵丙", 50, 8, 20); // 20%概率出现 reset_bots(); std::cout << "\n欢迎你," << player.name << "!你的任务是收集高价值物品并到达撤离点。\n"; std::cout<<"本局难度:"; if(current_difficulty == Difficulty::NORMAL) std::cout<<"【常规】敌人较弱,物资爆率较低\n"; else if(current_difficulty == Difficulty::SECRET) std::cout<<"【机密】均衡难度\n"; else if(current_difficulty == Difficulty::TOP_SECRET) std::cout<<"【绝密】敌人强悍,物资爆率提升!小心精英敌人!\n"; std::cout << "探索区域寻找容器,从中获取变卖物,注意敌人巡逻!\n"; std::cout << "武器系统:可拾取任意武器,装备时可选择替换已装备武器\n"; std::cout << "每探索25步会遇到黑市商店,可买卖物品\n"; std::cout << "前期(前20步)不会遇到精英敌人,放心探索!\n"; //大厅商店购买的开局礼物给到玩家 for(Item* gift : lobby_starting_gifts) { player.add_item(gift); } lobby_starting_gifts.clear(); //清空,下一局不会重复给 press_any_key(); current_state = GameState::EXPLORING;}
// 重置人机玩家状态
void reset_bots() {
for (auto& bot : bots) {
bot.reset();
}
}
// 创建变卖物3天前 来自 浙江
0(保险箱仅产出中等价值及以上)
void create_collectibles(stdvector<Item*>& items, int count, ContainerType container_type) {
// 根据容器类型调整价值等级
bool safe_only_mid_plus = (container_type == ContainerTypeSAFE || container_type == ContainerType::SMALL_SAFE);//====难度爆率修正==== int top_mod = 0; int high_mod =0; if(current_difficulty == Difficulty::NORMAL) { top_mod = -20; high_mod = -50; } else if(current_difficulty == Difficulty::TOP_SECRET) { top_mod = +40; high_mod = +80; } //机密不修改 // 价值概率(千分比) int top_chance = 0; int high_chance = 0; int mid_chance = 0; int low_chance = 0; int max_chance=0; if (container_type == ContainerType::SAFE) { max_chance=800; top_chance = 100; // 7% high_chance = 100; // 18% mid_chance = 0; // 50% low_chance = 0; // 保险箱无低价值 top_chance += top_mod; high_chance += high_mod; } else if (container_type == ContainerType::SMALL_SAFE) { max_chance = 700; top_chance = 100; // 3% high_chance = 100; // 17% mid_chance = 100; // 70% low_chance = 0; // 小保险箱无低价值top_chance += top_mod; high_chance += high_mod; } else if (container_type == ContainerType::MEDICAL_BOX) { max_chance = 600; top_chance = 200; // 3% high_chance = 100; // 17% mid_chance = 100; // 70% low_chance = 0; // 医疗箱同普通容器 top_chance += top_mod; high_chance += high_mod; } else if (container_type == ContainerType::STORAGE_BOX_S) { max_chance = 600; top_chance = 200; // 3% high_chance = 100; // 17% mid_chance = 100; // 70% low_chance = 0; //储物箱 top_chance += top_mod; high_chance += high_mod; } else if (container_type == ContainerType::SCATTERED || container_type == ContainerType::MANHOLE) { max_chance = 600; top_chance = 200; // 3% high_chance = 100; // 17% mid_chance = 100; // 70% low_chance = 0; // 散落物 井盖 top_chance += top_mod; high_chance += high_mod; }else { max_cha3天前 来自 浙江
0




















有帮助,赞一个