猫史档案馆


我的喵战代码

用户:UP主終黙UP主終黙查看:0 回复:3 评论:0 创建时间:2022-11-09T11:07:41


 

// ------------配置------------
const DEFAULT_WEAPON = 'UZI'; // 初始武器

// 队伍配置
const TEAM_CONFIG = {
    '红队': {
        spawnPoint: '红队出生点', // 出生点实体名称
        color: new Box3RGBColor(1, 0, 0), // 颜色
    },
    '黄队': {
        spawnPoint: '黄队出生点',
        color: new Box3RGBColor(1, 1, 0),
    },
};
// 武器配置
const WEAPON = {
    'S686': {
        damage: 50, // 伤害
        distance: 10, // 射程距离
        interval: 10, // 发射间隔(数值越大, 射速越慢)
        orientation: new Box3Quaternion(0, 1, 0, 0).rotateZ(-Math.PI / 2), // 装备方向
    },
    'UZI': {
        damage: 10,
        distance: 30,
        interval: 0,
        orientation: new Box3Quaternion(0, 1, 0, 0).rotateZ(-Math.PI / 2),
    },
    'AWM': {
        damage: 100,
        distance: 1000,
        interval: 100,
        orientation: new Box3Quaternion(0, 1, 0, 0).rotateZ(-Math.PI / 2).rotateX(Math.PI),
    },
    '神之刃': {
        damage: 10000, // 伤害
        distance: 1000000, // 射程距离
        interval: 0, // 发射间隔(数值越大, 射速越慢)
        orientation: new Box3Quaternion(0, 1, 0, 0).rotateZ(-Math.PI / 2), // 装备方向
    },
};
const GAME_END_TIME = 10 * 60; // 游戏结束时间, 单位秒
const GAME_END_SCORE = 30; // 游戏结束分数
const MIN_GAME_PLAYER_NUM = 2; // 最小游戏人数
const GAME_HALFTIME = 5; // 两局游戏间隔时间, 单位秒
// ----------------------------
const spawnPoint = objectMap(TEAM_CONFIG, ({spawnPoint}, team) => {
    const e = world.querySelector('#' + spawnPoint);
    e.onEntityContact(({entity, other}) => {
        if (!other.isPlayer) return; // 不处理非玩家的碰撞
        const { name } = other.player;
        if (!(name in playerState)) return; // 不处理非游戏中玩家的碰撞
        if (playerState[name].team === team) {
            // 碰到自家出生点恢复全部HP
            if (other.hp < other.maxHp) {
                other.hp = other.maxHp;
                other.player.directMessage('你回复了全部的HP');
            }
        } else {
            // 碰到非自家出生点, HP减半
            other.hurt(Math.ceil(other.hp / 2), { attacker: entity });
        }
    });
    return e.position.clone(); // 返回出生点位置
});

const defaultWeaponMesh = world.querySelector('#' + DEFAULT_WEAPON).mesh;
let playerState = {}; // 玩家状态
let teamScore = {}; // 队伍分数
let teamNum = {}; // 队伍人数
let gameEndResolve; // 用于结束游戏的函数

// 主函数
(async function main() {
    // 打印开始时间的日志
    console.log(`-------[${new Date().toISOString()}]--------`)
    setup(); // 初始化
    // 主循环, 不断检测并开始新的游戏
    for(;;await sleep(GAME_HALFTIME * 1000)) {
        // 检测人数
        if (world.querySelectorAll('player').length < MIN_GAME_PLAYER_NUM) {
            world.say(`当前人数不足${MIN_GAME_PLAYER_NUM}人, 无法开始游戏!`);
            continue;
        }
        // 倒计时
        world.say(`游戏即将开始!`);
        for (let i = 0; i > 0; i--) {
            await sleep(1000);
            world.say(`${i}...`);
        }
        // 开始新的一局游戏
        await start();
    }
})();

// 开始游戏
async function start() {
    console.log(`[${new Date().toISOString()}]开始新的一局游戏`);
    // 清空分数和队伍人数
    teamScore = objectMap(TEAM_CONFIG, () => 0);
    teamNum = objectMap(TEAM_CONFIG, () => 0);
    // 获取队伍名称
    const teamNames = Object.keys(TEAM_CONFIG);
    // 打乱所有玩家并执行队伍分配
    arrayShuffle(world.querySelectorAll('player')).forEach((entity, i) => {
        const teamName = teamNames[i % teamNames.length];
        joinTeam(entity, teamName);
        entity.player.directMessage(`你被分配到了${teamName}`);
    });
    // 等待游戏结束
    await new Promise(async (resolve) => {
        gameEndResolve = resolve; // 设置游戏结束函数
        await sleep(GAME_END_TIME * 1000); // 等待GAME_END_TIME秒
        resolve(); // 如果游戏没有提前结束, 就会由于到时间而结束
    });
    // 广播获胜队伍
    const winner = getMaxScore();
    world.say(`${winner}胜利, 总分: ${teamScore[winner]}`);
    let maxKd = 0; // 最高的kd
    let maxKdPlayer; // 最高kd的玩家
    // 计算每个玩家的KD并记录最高值
    for (const name in playerState) {
        const { entity, k, d } = playerState[name];
        const kd = k / (d + 1); // 计算公式: 击杀数/(喵数+1)
        // 告知每个玩家本局的kd
        entity.player.directMessage(`你本场游戏的评分为${kd.toFixed(2)}`);
        // 更新最大kd
        if (kd > maxKd) {
            maxKd = kd;
            maxKdPlayer = name;
        }
        // 喵家设置为非游戏状态
        entity.enableDamage = false;
        entity.player.cameraMode = 'FOLLOW';
        entity.player.color.set(1, 1, 1);
    }
    // 广播MVP(kd最高者)
    world.say(`本场游戏MVP为@${maxKdPlayer}, 评分是${maxKd.toFixed(2)}`);
    // 清空玩家状态和结束函数
    playerState = {};
    gameEndResolve = undefined;
}

// 加入队伍
function joinTeam(entity, team) {
    teamNum[team]++; // 队伍人数+1
    // 设置玩家属性
    entity.enableDamage = true;
    entity.player.cameraMode = 'FPS';
    entity.player.color.copy(TEAM_CONFIG[team].color);
    // 初始化玩家状态
    playerState[entity.player.name] = {
        team,
        entity,
        喵: DEFAULT_WEAPON,
        shootTick: 0,
        k: 0,
        d: 0,
    };
    // 装备武器
    entity.player.addWearable({
        bodyPart: Box3BodyPart.RIGHT_HAND, // 装备在右手上
        mesh: defaultWeaponMesh, // 设置武器mesh
        orientation: WEAPON[DEFAULT_WEAPON].orientation, // 调整方向
        scale: new Box3Vector3(0.3, 0.4, 0.2), // 调整大小
        offset: new Box3Vector3(0, -0.5, 0), //调整位置
    });
    entity.position.copy(spawnPoint[team]); // 传送到队伍的出生点
    entity.position.y = 10 + Math.random() * 20; // 随机增加y的偏移, 避免多个玩家相撞
    entity.player.spawnPoint.copy(entity.position); // 设置出生点
}

// 判断是否是游戏中的玩家
function isPlayer(entity) {
    return entity && entity.isPlayer && entity.player.name in playerState;
}

// 获取最高分的队伍名称
function getMaxScore() {
    let num = 0;
    let team;
    for (const key in teamScore) {
        if (teamScore[key] > num) {
            team = key;
            num = teamScore[key];
        }
    }
    return team;
}

// 获取最低分的队伍名称
function getMinTeam() {
    let num = Infinity;
    let team;
    for (const key in teamNum) {
        if (teamNum[key] < num) {
            team = key;
            num = teamNum[key];
        }
    }
    return team;
}

// 初始化
function setup() {
    // 处理喵
    world.onDie(({entity, attacker}) => {
        if (!attacker || !isPlayer(entity)) return; // 不处理出无击杀者的喵和非玩家的喵
        // 获取喵玩家名称和击杀者名称
        const { name } = entity.player;
        const killerName = attacker.isPlayer ? attacker.player.name : attacker.id;
        playerState[name].d++; // 喵数+1
        // 广播喵情况
        world.say(`@${killerName}击败了@${name}, 当前比分${Object.keys(teamScore).map((name) => `${name}:${teamScore[name]}`).join(', ')}`);

        // 如果击杀者是玩家
        if (attacker.isPlayer) {
            playerState[killerName].k++; // 击杀数+1
            teamScore[playerState[killerName].team]++; // 队伍分数+1
            // 判断是否达到比赛结束的比分
            if (teamScore[playerState[killerName].team] >= GAME_END_SCORE) gameEndResolve();
        }
    });
    // 初始化玩家
    world.onPlayerJoin(({ entity }) => {
        if (gameEndResolve) {
            // 游戏已经开始, 则加入人数组少的队伍
            const team = getMinTeam()
            joinTeam(entity, team);
            world.say(`玩家@${entity.player.name}加入${team}`);
        }
        // 处理玩家鼠标点击
        entity.player.onPress(({ tick, entity, button, raycast: { hitEntity, direction, distance } }) => {
            // 喵后点鼠标重生
            if (isPlayer(entity) && entity.hp === 0) {
                return entity.player.forceRespawn();
            }
            // 判断是否是鼠标左键, 击中实体是否是玩家, 以及击中的玩家是否喵
            if (button === 'action0' && isPlayer(entity) && isPlayer(hitEntity) && !hitEntity.dead) {
                // 获取双方的状态
                const state = playerState[entity.player.name];
                const otherState = playerState[hitEntity.player.name];
                if (state.team === otherState.team) return; // 相同队伍不处理
                const 喵 = WEAPON[state.喵]; // 获取武器信息
                if (state.shootTick + 喵.interval > tick) return; // 小于武器间隔事件不处理
                state.shootTick = tick; // 更新射击时间(tick)
                // 设置击中效果
                hitEntity.velocity.x += direction.x;
                //hitEntity.velocity.y += 2;
                hitEntity.velocity.z += direction.z;
                // 计算伤害并应用
                const basicDamage = Math.max(1, 喵.damage * Math.min(1, 喵.distance / distance));
                const damage = Math.ceil(basicDamage * (1 + Math.random() * 0.3));
                hitEntity.hurt(damage, { attacker: entity });
            }
        });
    });
    // 获取武器
    world.onEntityContact(({ entity, other }) => {
        // 必须是玩家触碰武器
        if (isPlayer(entity) && other.id in WEAPON) {
            const state = playerState[entity.player.name]; // 获取玩家状态
            if (!other.hasTag(state.team)) return; // 检查队伍
            state.喵 = other.id; // 设置武器
            entity.player.directMessage(`你获得了${other.id}`); // 通知玩家
            // 更新装备
            const handWearable = entity.player.wearables(Box3BodyPart.RIGHT_HAND)[0];
            handWearable.mesh = other.mesh;
            handWearable.orientation = WEAPON[other.id].orientation;
        }
        
    });
    // 收到伤害的通知
    world.onTakeDamage(({entity, damage, attacker}) => {
        if (!entity.isPlayer) return;
        const attackerName = attacker.isPlayer ? attacker.player.name : attacker.id;
        entity.player.directMessage(`[剩余HP: ${entity.hp}]: 你受到了${damage}点来自@${attackerName}的伤害`);
    });
}

// 随机打乱数组
function arrayShuffle (array) {
    for (let i = 1; i < array.length; ++i) {
        const temp = array[i];
        const x = (Math.random() * (i + 1)) | 0;
        array[i] = array[x];
        array[x] = temp;
    }
    return array;
}

// 为对象实现类似数组的map功能
function objectMap(obj, func) {
    const o = {};
    for (const key in obj) {
        o[key] = func(obj[key], key);
    }
    return o;
}
world.onPlayerJoin(({ entity }) => {//飞行特权代码(一开始就是)
    const TEST_PLAYER = [ '诡喵喵喵', '青莲宗.秀儿_琦玉的徒弟']//白名单
    if (!TEST_PLAYER.includes(entity.player.name)) return;
    entity.player.canFly = true;
});
world.onPress(async ({ entity, button }) => {
    if (button === Box3ButtonType.ACTION1) {
        if (entity.f) {
            entity.f = false;;
            for (let i = 0.1; i <= 0.45; i += 0.001) {
                await sleep(1);
                entity.player.cameraFovY = i;
            }
        } else if (!entity.f) {
            entity.f = true;
            for (let i = 0.45; i >= 0.1; i -= 0.001) {
                await sleep(1);
                entity.player.cameraFovY = i;
            }
        }
    }
});
var admin = ['诡喵喵喵', '青莲宗.秀儿_琦玉的徒弟']
world.onChat(({ entity, message }) => {
    if (admin.includes(entity.player.name)) {
        if (message == '变大') {
            entity.player.scale += 5;
            world.say(entity.player.name + '变大了')
        }
        if (message == '变小') {
            entity.player.scale += -0.5;
            world.say(entity.player.name + '变小了')
        }
        if (message == '还原大小') {
            entity.player.scale = 1;
            world.say(entity.player.name + '还原了大小')
        }
        if (message == '五灵飞甲') {
            entity.player.canFly = true;
            world.say(entity.player.name + '开启了飞行模式')
        }
        if (message == '解除飞行'){
            entity.player.canFly = false;
        	world.say(entity.player.name + '关闭了飞行模式')
            }
        if (message == '加速') {
            entity.player.walkSpeed = 100
            entity.player.runSpeed = 100
            entity.player.flySpeed = 100
            entity.player.swimSpeed = 100
            world.say(entity.player.name + '加速了')
        }
        if (message == '隐身') {
            entity.player.invisible = true;
            world.say(entity.player.name + '隐身了')
        }
        if (message == '现身') {
            entity.player.invisible = false;
            world.say(entity.player.name + '现身了')
        }
        if (message == '隐藏名字') {
            entity.player.showName = false;
            world.say(entity.player.name + '隐藏了名字')
        }
        if (message == '显示名字') {
            entity.player.showName = true;
            world.say(entity.player.name + '显示了名字')
        }
        if (message == '幽灵') {
            entity.player.spectator = true;
            world.say(entity.player.name + '开启了幽灵模式')
        }
        if (message == '解除幽灵') {
            entity.player.spectator = false;
            world.say(entity.player.name + '关闭了幽灵模式')
        }
        if (message == '发光') {
            entity.player.emissive = 1;//数值可调整
            world.say(entity.player.name + '开启了发光效果')
        }
        if (message == '还原发光') {
            entity.player.emissive = 0;
            world.say(entity.player.name + '还原了发光效果')
        }
        if (message == '反光') {
            entity.player.shininess = 1; world.say(entity.player.name + '开启了反光效果')
        }
        if (message == '还原反光') {
            entity.player.shininess = 0;
            world.say(entity.player.name + '还原了反光效果')
        }
        if (message == '变红色') {
            entity.player.color.set(1, 0, 0);//JS(1,0,0)表示红色,数字组合表示颜色
            world.say(entity.player.name + '变成了红色')
        }
        if (message == '变蓝色') {
            entity.player.color.set(0, 0, 1);
            world.say(entity.player.name + '变成了蓝色')
        }
        if (message == '变绿色') {
            entity.player.color.set(0, 1, 0);
            world.say(entity.player.name + '变成了绿色')
        }
        if (message == '变紫色') {
            entity.player.color.set(1, 0, 1);
            world.say(entity.player.name + '变成了紫色')
        }
        if (message == '变黄色') {
            entity.player.color.set(1, 1, 0);
            world.say(entity.player.name + '变成了黄色')
        }
        if (message == '变浅蓝色') {
            entity.player.color.set(0, 1, 1);
            world.say(entity.player.name + '变成了浅蓝色')
        }
        if (message == '还原颜色') {
            entity.player.color.set(1, 1, 1);
            world.say(entity.player.name + '还原了颜色')
        }
        if (message == '全部还原') {
            entity.player.scale = 1;
            entity.player.canFly = false;
            entity.player.showName = true;
            entity.player.spectator = false;
            entity.player.invisible = false;
            entity.player.emissive = 0;
            entity.player.shininess = 0;
            entity.player.color.set(1, 1, 1);
            Object.assign(entity, { particleRate: 250, });
            world.say(entity.player.name + '全部还原了');
        };
        if (message == '清屏') {
            for (let x = 0; x < 300; x++) {
                world.say('')
            }
        }
        if (message == '关闭粒子特效') {
            Object.assign(entity, { particleRate: 0, });
            world.say(entity.player.name + '关闭了粒子特效');
        }
        if (message == '开启粒子特效') {
            Object.assign(entity, { particleRate: 100, });
            world.say(entity.player.name + '开启了粒子特效'); 
        }
    }
})

 


回复

上一页1 页 / 共 1下一页
UP主終黙UP主終黙

技术喵,你吞我排版!

点赞0


评论


盗码师盗码师

纯属复制的吧

点赞0


评论


UP主終黙UP主終黙

不是

 

点赞0


评论