float dmsp_skill = 0;
float dmsp_nextComboTime = -1;
float dmsp_combo = 1;
float dmsp_score = 0;
// Create a target_null for every deathmatch spawnpoint, because func_spawners reject
// anything that isn't a target_null for some strange reason
// 为 每个 DeathMatch SpawnPoint 创建一个target_null,
// 因为 func_spawners拒绝。
//由于某些奇怪的原因,任何不是target_null的内容
float dmsp_createSpawns()
{
float i, j = 0;
entity spawny, newNull;
string namey;
for (i = 1; i < 64; i++)
{
namey = ("info_player_deathmatch_" + i);
spawny = sys.getEntity(namey);
if (spawny)
{
namey = "dudeSpawnPoint_" + j;
sys.setSpawnArg( "name", namey );
sys.setSpawnArg( "origin", spawny.getWorldOrigin() );
newNull = sys.spawn( "target_null" );
j++;
}
}
return j;
}
// Set spawnargs of the func_spawner to target all of the new spawn nulls
// 将 func_spawner 的 spawnargs 设置为 以所有 新生成的 null 为 目标
void dmsp_setSpawns( float j )
{
float i;
entity spawny;
string namey;
for (i = 0; i <= j; i++)
{
namey = ("dudeSpawnPoint_" + i);
spawny = sys.getEntity(namey);
if (spawny)
{
sys.setSpawnArg("target_" + i, namey );
}
}
}
// score!
// take the given score and display it with the ordinarily dev-only function sys.drawText
// and float/shrink it per frame for extra arcade cach?
// 得分!
//获取 给定的 得分,
//并使用 通常 仅用于开发的函数sys.drawText 显示它。
//并 每帧 浮动/收缩它,以获得 额外的 街机缓存?
void dmsp_scorePip ( string text, vector origin, float pipTime )
{
float frameTime = sys.getFrameTime( );
float startTime = sys.getTime( );
float i, d, score;
vector org = origin, color;
string comboType;
if (startTime <= dmsp_nextComboTime) dmsp_combo = dmsp_combo + 1;
else dmsp_combo = 1;
dmsp_nextComboTime = startTime + 2 * pipTime;
// window until combo cutoff
// 窗口 直到 组合框 关闭
score = sys.strToFloat( text ) * dmsp_combo;
pipTime = pipTime + ( 0.25 * pipTime * ( dmsp_combo - 1 ) );
for ( i = startTime; i < (startTime + pipTime); i = i + frameTime )
{
d = (i - startTime) / pipTime;
// pick a lerping color & extra floaty text print based on combo level
// this feels kind of unwieldy but without arrays or case switches it's the best we can do
// 根据 组合级别 选择Lerping颜色 和 额外的 浮动 文本 打印。
// 这感觉有点 笨拙,但没有 数组或大小写 切换,这是我们能做的最好的。
if (dmsp_combo == 1)
{
color_x = 1 - d; // red
}
else if (dmsp_combo == 2)
{
color_x = 1 - d;
color_y = 0.5 * ( 1 - d ); // orange
comboType = "Combo!";
}
else if (dmsp_combo == 3)
{
color_x = 1 - d;
color_y = 1 - d; // yellow
comboType = "Double Combo!";
}
else if (dmsp_combo == 4)
{
color_y = 1 - d; // green
comboType = "Triple Combo!";
}
else if (dmsp_combo == 5)
{
color_y = 1 - d;
color_z = 1 - d; // cyan
comboType = "Super Combo!";
}
else if (dmsp_combo == 6)
{
color_y = 0.5 * ( 1 - d );
color_z = 1 - d; // light blue
comboType = "Mega Combo!";
}
else if (dmsp_combo == 7)
{
color_z = 1 - d; // deep blue
comboType = "Ultra Combo!";
}
else if (dmsp_combo >= 8)
{
color_x = color_y = color_z = 1 - d; // white
comboType = "Holy Shit!";
}
org_z = origin_z + d * 96;
sys.drawText( score, org, 0.5 * (1 - d), color, 1, 0 );
if (dmsp_combo > 1)
{
org_z = origin_z + d * 96 + 12;
sys.drawText( comboType, org, 0.25 * ( 1 - d ), color, 1, 0 );
}
sys.waitFrame( );
}
dmsp_score = dmsp_score + score;
// The only way to show the player his score is to update it in the
//向玩家显示其分数的唯一方法是在
sys.println( dmsp_score );
// console since there's no way to display it on the player hud
// 控制台,因为 无法在 播放器HUD上 显示 它
}
// Sprinkle goodies around a given point
//在 给定点 周围 撒上 供给
void dmsp_throwLoots ( vector org,
string lootClass,
float cnt,
float nodoubles
)
{
float i;
entity loots;
vector toss;
float dist = 128; // radius distance to spawn goodies
// 生成 好东西的 半径距离
float doubChance = 1 - ( 0.1 * dmsp_skill );
// more double drops on harder skill to keep the player stocked
// 在更难的技能上 有更多的 双倍掉落,以保持 玩家的 储备。
if ( sys.random(1) > doubChance && nodoubles == 0 )
{
cnt = cnt * 2; // twice the goodies
// 两倍的 供给品
dist = 192;
}
for( i = 0; i < cnt; i++ )
{
toss_x = dist - sys.random(2 * dist);
toss_y = dist - sys.random(2 * dist);
toss_z = dist;
sys.setSpawnArg( "origin", org );
sys.setSpawnArg( "nodrop", 1 );
loots = sys.spawn( lootClass );
sys.waitFrame(); // wait until entity exists to set toss velocity
loots.setLinearVelocity( toss );
}
}
// Drop one of the single player weapon mods
void dmsp_throwMod( vector org )
{
string mod;
entity loots;
vector toss;
toss_x = 128 - sys.random(256);
toss_y = 128 - sys.random(256);
toss_z = 128;
float val = sys.random(10);
if (val > 9) mod = "weaponmod_shotgun_ammo";
else if (val > 8) mod = "weaponmod_machinegun_ammo";
else if (val > 7) mod = "weaponmod_hyperblaster_bounce1";
else if (val > 6) mod = "weaponmod_hyperblaster_bounce2";
else if (val > 5) mod = "weaponmod_nailgun_seek";
else if (val > 4) mod = "weaponmod_nailgun_power";
else if (val > 3) mod = "weaponmod_railgun_penetrate";
else if (val > 2) mod = "weaponmod_rocketlauncher_seek";
else if (val > 1) mod = "weaponmod_rocketlauncher_burst";
else mod = "weaponmod_lightninggun_chain";
sys.setSpawnArg( "model", "models/pick_ups/mp_pickups/moderator.lwo" ); // give it a better/more noticeable model
sys.setSpawnArg( "origin", org );
loots = sys.spawn( mod );
sys.waitFrame(); // wait until entity exists to set toss velocity
loots.setLinearVelocity( toss );
}
// check the killed monster's spawnclass and decide on a drop and score
void dmsp_killMonster( entity victim )
{
string vicType = victim.getKey( "classname" ); // what kind of monster is it?
vector vicOrg, vicSize, vicDrop, vicPip;
float score = (dmsp_skill + 1) * 25 * dmsp_combo; // score on general = 4x score on easy
vicOrg = victim.getWorldOrigin(); // where was it killed?
vicSize = victim.getSize(); // how big was it? for deciding how high to toss items and print score
vicDrop = vicOrg;
vicDrop_z = vicDrop_z + vicSize_z * 0.5; // drop items waist high
vicPip = vicOrg;
vicPip_z = vicPip_z + vicSize_z * 0.75; // print score pip about head high
float val = sys.random(1);
if ( vicType == "monster_strogg_marine" ) {
if ( val > 0.7 ) dmsp_throwLoots( vicDrop, "ammo_hyperblaster_mp", 1, 0 );
else if ( val > 0.5 ) dmsp_throwLoots( vicDrop, "item_health_shard_mp", 1, 0);
else if ( val > 0.3 ) dmsp_throwLoots( vicDrop, "item_armor_shard", 1, 0);
thread dmsp_scorePip( score, vicPip, 1 );
} else if ( vicType == "monster_strogg_marine_sgun" ) {
if ( val > 0.7 ) dmsp_throwLoots( vicDrop, "ammo_shotgun_mp", 1, 0 );
else if ( val > 0.5 ) dmsp_throwLoots( vicDrop, "item_health_shard_mp", 1, 0);
else if ( val > 0.3 ) dmsp_throwLoots( vicDrop, "item_armor_shard", 1, 0);
thread dmsp_scorePip( score, vicPip, 1 );
} else if ( vicType == "monster_strogg_marine_mgun" ) {
if ( val > 0.7 ) dmsp_throwLoots( vicDrop, "ammo_machinegun_mp", 1, 0 );
else if ( val > 0.5 ) dmsp_throwLoots( vicDrop, "item_health_shard_mp", 1, 0 );
else if ( val > 0.3 ) dmsp_throwLoots( vicDrop, "item_armor_shard", 1, 0 );
thread dmsp_scorePip( score, vicPip, 1 );
} else if ( vicType == "monster_sentry" ) {
if ( val > 0.66 ) dmsp_throwLoots( vicDrop, "item_armor_shard", 4, 0 );
else if ( val > 0.33 ) dmsp_throwMod( vicDrop ); // 1/3 chance of dropping a sexy weaponmod
else dmsp_throwLoots( vicDrop, "item_health_shard_mp", 4, 0 );
score = score * 2;
thread dmsp_scorePip( score, vicPip, 1.25 );
} else if ( vicType == "monster_grunt" ) {
if ( val > 0.5 ) dmsp_throwLoots( vicDrop, "item_health_small_mp", 1, 0 );
score = score * 3;
thread dmsp_scorePip( score, vicPip, 1 );
} else if ( vicType == "monster_berserker" ) {
if ( val > 0.5 ) dmsp_throwLoots( vicDrop, "item_health_small_mp", 1, 0 );
else if ( val > 0.2 ) dmsp_throwLoots( vicDrop, "ammo_lightninggun_mp", 1, 0 );
score = score * 3;
thread dmsp_scorePip( score, vicPip, 1 );
} else if ( vicType == "monster_gunner" ) {
if ( val > 0.6 ) dmsp_throwLoots( vicDrop, "ammo_nailgun_mp", 1, 0 );
else if ( val > 0.2 ) dmsp_throwLoots( vicDrop, "ammo_grenadelauncher_mp", 1, 0 );
else dmsp_throwLoots( vicDrop, "item_health_small_mp", 1, 0 );
score = score * 3;
thread dmsp_scorePip( score, vicPip, 1 );
} else if ( vicType == "monster_iron_maiden" ) {
if ( val > 0.6 ) dmsp_throwLoots( vicDrop, "ammo_rocketlauncher_mp", 1, 0 );
else if ( val > 0.3 ) dmsp_throwLoots( vicDrop, "ammo_hyperblaster_mp", 1, 0 );
else dmsp_throwLoots( vicDrop, "item_health_small_mp", 1, 0 );
score = score * 5;
thread dmsp_scorePip( score, vicPip, 1.25 );
} else if ( vicType == "monster_gladiator" ) {
if ( val > 0.6 ) dmsp_throwLoots( vicDrop, "ammo_railgun_mp", 1, 0 );
else if ( val > 0.3 ) dmsp_throwLoots( vicDrop, "item_health_small_mp", 1, 0 );
else if ( val > 0.2 ) dmsp_throwLoots( vicDrop, "item_health_large_mp", 1, 0 );
score = score * 6;
thread dmsp_scorePip( score, vicPip, 1.25 );
} else if ( vicType == "monster_lt_tank" ) {
if ( val > 0.5 ) dmsp_throwLoots( vicDrop, "ammo_rocketlauncher_mp", 2, 0 );
else if ( val > 0.2 ) dmsp_throwLoots( vicDrop, "item_armor_large_mp", 1, 1 );
else dmsp_throwLoots( vicDrop, "item_health_mega", 1, 1 );
score = score * 10;
thread dmsp_scorePip( score, vicPip, 1.5 );
}
}
// play effects on spawn so guys don't just blink into view
// this doesn't work on every monster, because guys like monster_sentry don't have chest bones
// but setting this up special for each skeleton isn't worth the cruft
void dmsp_whoosh( entity me )
{
me.playEffect( "fx_burn_particles_chest", "chest", 0 );
me.playEffect( "fx_burn_particles_chest", "head", 0 );
me.playEffect( "fx_burn_particles_chest", "origin", 0 );
}
// Create the func_spawner that drives the whole thing
// All arguments must be set on the spawner when it spawns, hence spawnArgs rather than setKeys
void dmsp_createSpawner()
{
float j = dmsp_createSpawns(); // make nulls for spawn points
// high odds for puny dudes, so list them several times
sys.setSpawnArg("def_spawn", "monster_strogg_marine");
sys.setSpawnArg("def_spawn_1", "monster_strogg_marine");
sys.setSpawnArg("def_spawn_2", "monster_strogg_marine");
sys.setSpawnArg("def_spawn_3", "monster_strogg_marine");
sys.setSpawnArg("def_spawn_4", "monster_strogg_marine_sgun");
sys.setSpawnArg("def_spawn_5", "monster_strogg_marine_sgun");
sys.setSpawnArg("def_spawn_6", "monster_strogg_marine_sgun");
sys.setSpawnArg("def_spawn_7", "monster_strogg_marine_sgun");
sys.setSpawnArg("def_spawn_8", "monster_strogg_marine_mgun");
sys.setSpawnArg("def_spawn_9", "monster_strogg_marine_mgun");
sys.setSpawnArg("def_spawn_10", "monster_strogg_marine_mgun");
sys.setSpawnArg("def_spawn_11", "monster_strogg_marine_mgun");
// medium odds for medium guys
sys.setSpawnArg("def_spawn_12", "monster_gunner");
sys.setSpawnArg("def_spawn_13", "monster_gunner");
sys.setSpawnArg("def_spawn_14", "monster_grunt");
sys.setSpawnArg("def_spawn_15", "monster_grunt");
sys.setSpawnArg("def_spawn_16", "monster_sentry");
sys.setSpawnArg("def_spawn_17", "monster_sentry");
sys.setSpawnArg("def_spawn_18", "monster_berserker");
sys.setSpawnArg("def_spawn_19", "monster_berserker");
// low odds for tough SOBs
sys.setSpawnArg("def_spawn_20", "monster_iron_maiden");
sys.setSpawnArg("def_spawn_21", "monster_gladiator");
sys.setSpawnArg("def_spawn_22", "monster_lt_tank");
sys.waitFrame();
sys.setSpawnArg("max_active", j); // assume # of spawns in map is a good monster limit
sys.setSpawnArg("delay", ( 5 - dmsp_skill ) ); // shorter delay on harder skill
sys.setSpawnArg("auto_target", "1");
sys.setSpawnArg("face_enemy", "1");
sys.setSpawnArg("skipVisible", "0");
sys.setSpawnArg("remove", "0"); // don't disappear from the entity list if I break this
// spawn_* keys are set on the spawned monster:
sys.setSpawnArg("spawn_neverdormant", "1");
sys.setSpawnArg("spawn_script_death", "dmsp_killMonster"); // for spawning loots
sys.setSpawnArg("spawn_script_init", "dmsp_whoosh"); // for spawning zoots
sys.waitFrame();
dmsp_setSpawns( j ); // set previously created nulls as possible targets
entity dudeSpawner = sys.spawn( "func_spawner" );
sys.trigger(dudeSpawner);
}
void main()
{
dmsp_skill = sys.strToFloat( sys.getcvar("g_skill") );
// Spawn all possible monsters and items in main to force them to cache when the map loads
// then remove them out of the way
entity tempy, tempy2, tempy3; // three at a time so it doesn't take 30 game frames
tempy = sys.spawn( "monster_strogg_marine" );
tempy2 = sys.spawn( "monster_strogg_marine_sgun" );
tempy3 = sys.spawn( "monster_strogg_marine_mgun" );
sys.waitFrame();
tempy.remove(); tempy2.remove(); tempy3.remove();
tempy = sys.spawn( "monster_gunner" );
tempy2 = sys.spawn( "monster_grunt" );
tempy3 = sys.spawn( "monster_iron_maiden" );
sys.waitFrame();
tempy.remove(); tempy2.remove(); tempy3.remove();
tempy = sys.spawn( "monster_berserker" );
tempy2 = sys.spawn( "monster_sentry" );
tempy3 = sys.spawn( "monster_gladiator" );
sys.waitFrame();
tempy.remove(); tempy2.remove(); tempy3.remove();
tempy = sys.spawn( "monster_lt_tank" );
tempy2 = sys.spawn( "item_health_small_mp" );
tempy3 = sys.spawn( "item_health_large_mp" );
sys.waitFrame();
tempy.remove(); tempy2.remove(); tempy3.remove();
tempy = sys.spawn( "ammo_machinegun_mp" );
tempy2 = sys.spawn( "ammo_shotgun_mp" );
tempy3 = sys.spawn( "ammp_hyperblaster_mp" );
sys.waitFrame();
tempy.remove(); tempy2.remove(); tempy3.remove();
tempy = sys.spawn( "ammo_nailgun_mp" );
tempy2 = sys.spawn( "ammo_railgun_mp" );
tempy3 = sys.spawn( "ammo_lightninggun_mp" );
sys.waitFrame();
tempy.remove(); tempy2.remove(); tempy3.remove();
tempy = sys.spawn( "ammo_grenadelauncher_mp" );
tempy2 = sys.spawn( "ammo_rocketlauncher_mp" );
tempy3 = sys.spawn( "ammo_machinegun_mp" );
sys.waitFrame();
tempy.remove(); tempy2.remove(); tempy3.remove();
tempy = sys.spawn( "item_health_mega" );
tempy2 = sys.spawn( "item_armor_large_mp" );
tempy3 = sys.spawn( "item_armor_shard_mp" );
sys.waitFrame();
tempy.remove(); tempy2.remove(); tempy3.remove();
tempy = sys.spawn( "item_health_shard_mp" );
sys.waitFrame();
tempy.remove();
sys.wait(2);
sys.println("Three ... ");
sys.wait(1);
sys.println("Two ... ");
sys.wait(1);
sys.println("One ... ");
sys.wait(1);
dmsp_createSpawner();
sys.println("The invasion has begun!");
}
如果你新建了一个新的地图的话,或者怪物
所有评论(0)