如何让PumpBomb_Exp重复3-5次或持续10-15秒?while循环失效求助
手雷爆炸特效重复触发问题与解决
问题说明
需要在游戏环境中实现PumpBomb_Exp(手雷爆炸效果方法)重复执行3-5次,或让特效持续显示10-15秒。尝试用while循环实现,但游戏测试中特效未重复触发,无预期效果。
原代码核心问题
你写的while循环存在两个致命问题:
- 变量名冲突:外层while循环的计数器
i,被内部for循环的new i = 0覆盖(Pawn语言中new会创建局部变量),导致外层i永远保持初始值1,循环逻辑完全失效。 - 同步循环阻塞帧:游戏是单线程运行,同步while循环会一次性执行所有特效代码,玩家视觉上只会看到一次效果,还会阻塞游戏线程导致卡顿。
解决方案:使用异步定时器
游戏开发中重复触发特效必须用异步定时器,避免阻塞主线程,同时实现间隔触发。以下是修改思路和代码示例:
1. 拆分逻辑,避免重复伤害
把爆炸伤害计算放在第一次触发时执行,后续仅重复显示特效,防止多次攻击玩家。
2. 用set_task创建定时任务
通过AMX Mod X的set_task函数,每隔指定时间(比如2秒)触发一次特效,重复3-5次即可覆盖10-15秒的持续时间。
修改后代码示例
// 主爆炸函数:执行伤害+首次特效,启动定时任务 public PumpBomb_Exp(Ent, Float:Origin[3], Owner, Team) { // 仅执行一次伤害计算 static Float:PlayerOrigin[3] for(new idx = 0; idx < g_MaxPlayers; idx++) { if(!is_user_alive(idx)) continue if(get_player_team(idx) == Team) continue pev(idx, pev_origin, PlayerOrigin) if(get_distance_f(Origin, PlayerOrigin) > PUMPKIN_RADIUS) continue if(!is_user_connected(Owner)) Owner = idx ExecuteHamB(Ham_TakeDamage, idx, "grenade", Owner, PUMPKIN_DAMAGE, DMG_CRUSH) } // 首次音效与特效 emit_sound(Ent, CHAN_BODY, WeaponSounds[0], 1.0, ATTN_NORM, 0, PITCH_NORM) static Float:flOrigin[3] pev(Ent, pev_origin, flOrigin) engfunc(EngFunc_EmitSound, Ent, CHAN_WEAPON, g_soundexpl, 1.0, ATTN_NORM, 0, PITCH_NORM) DrawExplosionEffects(flOrigin) // 启动定时任务:每隔2秒触发一次,重复4次(总共5次),持续10秒 new params[12]; params[0] = Ent; memcpy(params[1], Origin, sizeof(Origin)); set_task(2.0, "Task_RepeatExplosion", _, params, sizeof(params), "a", 4); } // 定时触发的特效函数 public Task_RepeatExplosion(params[]) { new Ent = params[0]; Float:Origin[3]; memcpy(Origin, params[1], sizeof(Origin)); // 重复音效 emit_sound(Ent, CHAN_BODY, WeaponSounds[0], 1.0, ATTN_NORM, 0, PITCH_NORM) static Float:flOrigin[3] pev(Ent, pev_origin, flOrigin) engfunc(EngFunc_EmitSound, Ent, CHAN_WEAPON, g_soundexpl, 1.0, ATTN_NORM, 0, PITCH_NORM) // 绘制爆炸特效 DrawExplosionEffects(flOrigin) } // 抽离的特效绘制函数,复用代码 stock DrawExplosionEffects(Float:flOrigin[3]) { // 爆炸特效1 message_begin(MSG_BROADCAST, SVC_TEMPENTITY) write_byte(TE_EXPLOSION) engfunc(EngFunc_WriteCoord, flOrigin[0]) engfunc(EngFunc_WriteCoord, flOrigin[1]) engfunc(EngFunc_WriteCoord, flOrigin[2] + 16.0) write_short(g_Exp_SprId) write_byte(50) // 缩放比例(单位0.1) write_byte(30) // 帧率 write_byte(4) // 标志位 message_end() // 爆炸特效2 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, flOrigin, 0) write_byte(TE_EXPLOSION) engfunc(EngFunc_WriteCoord, flOrigin[0]) engfunc(EngFunc_WriteCoord, flOrigin[1]) engfunc(EngFunc_WriteCoord, flOrigin[2]+50.0) write_short(spriteexpl) write_byte(30) write_byte(10) write_byte(0) message_end() // 灯光特效 message_begin(MSG_BROADCAST, SVC_TEMPENTITY) write_byte(TE_DLIGHT) engfunc(EngFunc_WriteCoord, flOrigin[0]) engfunc(EngFunc_WriteCoord, flOrigin[1]) engfunc(EngFunc_WriteCoord, flOrigin[2]) write_byte(45)//半径 write_byte(250) // 红 write_byte(150) // 绿 write_byte(50) // 蓝 write_byte(15) // 生命周期 write_byte(10) message_end() // 贴花特效 engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, flOrigin, 0) write_byte(TE_WORLDDECAL) engfunc(EngFunc_WriteCoord, flOrigin[0]) engfunc(EngFunc_WriteCoord, flOrigin[1]) engfunc(EngFunc_WriteCoord, flOrigin[2]) write_byte(engfunc(EngFunc_DecalIndex,"{scorch3")) message_end() // 环形特效1 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, flOrigin, 0) write_byte(TE_BEAMCYLINDER) // TE标识 engfunc(EngFunc_WriteCoord, flOrigin[0]) // x坐标 engfunc(EngFunc_WriteCoord, flOrigin[1]) // y坐标 engfunc(EngFunc_WriteCoord, flOrigin[2]) // z坐标 engfunc(EngFunc_WriteCoord, flOrigin[0]) // x轴 engfunc(EngFunc_WriteCoord, flOrigin[1]) // y轴 engfunc(EngFunc_WriteCoord, flOrigin[2] + 35) // z轴 write_short(g_sprRing) // 精灵 write_byte(0) // 起始帧 write_byte(0) // 帧率 write_byte(10) // 生命周期 write_byte(65) // 宽度 write_byte(0) // 噪点 write_byte(255) // 红 write_byte(155) // 绿 write_byte(55) // 蓝 write_byte(200) // 亮度 write_byte(0) // 速度 message_end() // 环形特效2 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, flOrigin, 0) write_byte(TE_BEAMCYLINDER) // TE标识 engfunc(EngFunc_WriteCoord, flOrigin[0]) // x坐标 engfunc(EngFunc_WriteCoord, flOrigin[1]) // y坐标 engfunc(EngFunc_WriteCoord, flOrigin[2]) // z坐标 engfunc(EngFunc_WriteCoord, flOrigin[0]) // x轴 engfunc(EngFunc_WriteCoord, flOrigin[1]) // y轴 engfunc(EngFunc_WriteCoord, flOrigin[2] + 65) // z轴 write_short(g_sprRing) // 精灵 write_byte(0) // 起始帧 write_byte(0) // 帧率 write_byte(10) // 生命周期 write_byte(35) // 宽度 write_byte(0) // 噪点 write_byte(255) // 红 write_byte(155) // 绿 write_byte(55) // 蓝 write_byte(200) // 亮度 write_byte(0) // 速度 message_end() // 环形特效3 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, flOrigin, 0) write_byte(TE_BEAMCYLINDER) // TE标识 engfunc(EngFunc_WriteCoord, flOrigin[0]) // x坐标 engfunc(EngFunc_WriteCoord, flOrigin[1]) // y坐标 engfunc(EngFunc_WriteCoord, flOrigin[2]) // z坐标 engfunc(EngFunc_WriteCoord, flOrigin[0]) // x轴 engfunc(EngFunc_WriteCoord, flOrigin[1]) // y轴 engfunc(EngFunc_WriteCoord, flOrigin[2] + 95) // z轴 write_short(g_sprRing) // 精灵 write_byte(0) // 起始帧 write_byte(0) // 帧率 write_byte(10) // 生命周期 write_byte(15) // 宽度 write_byte(0) // 噪点 write_byte(255) // 红 write_byte(155) // 绿 write_byte(55) // 蓝 write_byte(200) // 亮度 write_byte(0) // 速度 message_end() }
关键修改点
- 抽离
DrawExplosionEffects函数,复用特效代码,减少冗余。 - 使用
set_task异步触发特效,参数"a", 4表示重复4次(加上首次共5次),间隔2秒,总时长10秒。 - 伤害计算仅执行一次,避免重复攻击玩家。
- 修复变量名冲突问题,将内部循环计数器改为
idx,避免覆盖外层变量。
内容的提问来源于stack exchange,提问作者Tech2cool
相关产品推荐
相关产品推荐

