Game Modding | Call of Duty: Black Ops 3 | Scripting
Atchfam77:
Hello! I have been trying to design a "quality of life" changes mod recently. The features included are an increased perk limit, max ammos refill your magazine, carpenter repairs your shield, you spawn in with the RK5, and Widows Wine provides explosive resistance. I have been able to get each feature working on Shadows so far, and the perk limit/RK5 works on every map. The issues I am having are with the carpenter, Widows, and max ammo changes.
On maps without a shield, I get a crash loading the map, and on all of the Chronicles maps, the change to the two powerups and the perk don't function at all.
Here is the beginning to the Carpenter file. I used HarryBO21's carpenter release to modify the base script from the share folder.
#using scripts\codescripts\struct;
#using scripts\shared\clientfield_shared;
#using scripts\shared\system_shared;
#using scripts\shared\util_shared;
#insert scripts\shared\shared.gsh;
#insert scripts\shared\version.gsh;
#using scripts\shared\ai\zombie_death;
#using scripts\zm\_zm_blockers;
#using scripts\zm\_zm_pers_upgrades;
#using scripts\zm\_zm_pers_upgrades_functions;
#using scripts\zm\_zm_powerups;
#using scripts\zm\_zm_score;
#using scripts\zm\_zm_spawner;
#using scripts\zm\_zm_utility;
#insert scripts\zm\_zm_weapons.gsh;
#insert scripts\zm\_zm_powerups.gsh;
#insert scripts\zm\_zm_utility.gsh;
#using scripts\zm\_zm_weap_riotshield;
#define BOARD_REPAIR_DISTANCE_SQUARED 750 * 750
#precache( "string", "ZOMBIE_POWERUP_MAX_AMMO" );
#namespace zm_powerup_carpenter;
REGISTER_SYSTEM( "zm_powerup_carpenter", &__init__, undefined )
//-----------------------------------------------------------------------------------
// setup
//-----------------------------------------------------------------------------------
function __init__()
{
zm_powerups::register_powerup( "carpenter", &grab_carpenter );
if( ToLower( GetDvarString( "g_gametype" ) ) != "zcleansed" )
{
zm_powerups::add_zombie_powerup( "carpenter", "p7_zm_power_up_carpenter", &"ZOMBIE_POWERUP_MAX_AMMO", &func_should_drop_carpenter, !POWERUP_ONLY_AFFECTS_GRABBER, !POWERUP_ANY_TEAM, !POWERUP_ZOMBIE_GRABBABLE );
}
level.use_new_carpenter_func = &start_carpenter_new;
}
function grab_carpenter( player )
{
// Check for the carpenter persistent upgrade
if( zm_utility::is_Classic() )
{
player thread zm_pers_upgrades::persistent_carpenter_ability_check();
}
if( isDefined(level.use_new_carpenter_func) )
{
level thread [[level.use_new_carpenter_func]](self.origin);
}
else
{
level thread start_carpenter( self.origin );
}
player thread zm_powerups::powerup_vo( "carpenter" );
player thread carpenter_repair_player_shield();
}
function carpenter_repair_player_shield()
{
if( !IS_TRUE( self.hasRiotShield ) )
return;
self riotshield::player_set_shield_health( 1, 1 );
w_weapon = self getCurrentWeapon();
self takeWeapon( self.weaponRiotshield );
self giveWeapon( self.weaponRiotshield );
if ( w_weapon.isriotshield )
self switchToWeapon( self.weaponRiotshield );
}
Next, the only change I made to the max ammo default script was around line 112ish, where I got the code from Abnormal202.
if ( players[i] HasWeapon( primary_weapons[x] ) )
{
players[i] GiveMaxAmmo( primary_weapons[x] );
players[i] SetWeaponAmmoClip( primary_weapons[x], primary_weapons[x].clipSize);
}
Last, my change to Widows Wine is thanks to PROxFTW. I used his public release PHD script to figure out how the game handles negating explosive damage. The first line is placed in the default script under the "enable_widows_wine_perk_for_level" function. The other stuff I just threw at the bottom of the script since it could pretty much be anywhere.
zm::register_player_damage_callback( &widows_pseudoPHD_player_damage_override ); //damage override for PhD ability
function widows_pseudoPHD_player_damage_override( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime )
{
if( sMeansOfDeath == "MOD_PROJECTILE" || sMeansOfDeath == "MOD_PROJECTILE_SPLASH" || sMeansOfDeath == "MOD_GRENADE" || sMeansOfDeath == "MOD_GRENADE_SPLASH" || sMeansOfDeath == "MOD_EXPLOSIVE" || sMeansOfDeath == "MOD_SUICIDE" )
{
if ( self HasPerk( PERK_WIDOWS_WINE ) )
{
return 0;
}
}
return -1;
}
In my main script file, which is the template from CabConModding, I have the RK5 and perk limit changes. Here is that code. I have #using for all of my modified scripts written in this file, with the carpenter one being commented out for the time being since it doesn't work on most Chronicles maps.
#using scripts\codescripts\struct;
#using scripts\shared\callbacks_shared;
#using scripts\shared\system_shared;
#using scripts\shared\array_shared;
#using scripts\shared\flag_shared;
#using scripts\shared\array_shared;
#using scripts\shared\callbacks_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\compass;
#using scripts\shared\exploder_shared;
#using scripts\shared\flag_shared;
#using scripts\shared\laststand_shared;
#using scripts\shared\math_shared;
#using scripts\shared\scene_shared;
#using scripts\shared\util_shared;
#using scripts\zm\_zm_score;
#using scripts\zm\_zm_perks;
#using scripts\zm\_zm_utility;
#using scripts\zm\_zm_stats;
#using scripts\zm\_zm;
#using scripts\zm\_zm_powerups;
#insert scripts\shared\shared.gsh;
#insert scripts\shared\version.gsh;
#insert scripts\zm\_zm_utility.gsh;
#using scripts\zm\gametypes\_zm_perk_widows_wine;
//#using scripts\zm\gametypes\_zm_powerup_carpenter;
#using scripts\zm\gametypes\_zm_powerup_full_ammo;
//#using scripts\zm\_zm_weap_riotshield;
#namespace clientids;
REGISTER_SYSTEM( "clientids", &__init__, undefined )
function __init__()
{
callback::on_start_gametype( &init );
callback::on_connect( &on_player_connect );
callback::on_spawned( &on_player_spawned );
}
function init()
{
level.clientid = 0;
}
function on_player_connect()
{
self.clientid = matchRecordNewPlayer( self );
if ( !isdefined( self.clientid ) || self.clientid == -1 )
{
self.clientid = level.clientid;
level.clientid++;
}
level thread set_perk_limit(50);
}
function on_player_spawned() //this function will get called on every spawn!
{
weapon = getweapon("pistol_burst"); //sets the variable named "weapon" to the RK5
custom = self GetBuildKitWeapon (weapon); //retrieves the RK5 from weapon kits (only attachments)
camo = self GetBuildKitWeaponOptions (weapon); //retrieves the camo from RK5 weapon kit
self GiveWeapon(custom, camo); //gives the player their custom RK5 with its camo and attachments
self SwitchToWeapon(custom);
level flag::wait_till( "initial_blackscreen_passed" ); //waits until blackscreen is gone
self IPrintLnBold("^1Thanks for using DuhJudge's QOL mod!"); //prints thanks screen
primaryWeapons = self GetWeaponsList(); // creates a list of the current player's weapons
for( x = 0; x < primaryWeapons.size; x++ ) // for loop to cycle through weapon list
{
self GiveMaxAmmo( primaryWeapons[x] ); // updating ammo count for each weapon
}
}
function set_perk_limit(num)
{
wait( 30 );
level.perk_purchase_limit = num;
}
TLDR:
Everything here works, but only on SoE. On maps without a shield, the map crashes on the loading screen. On Chronicles maps, the max ammo, carpenter, and widows wine scripts do not function.
Here is what my zone file looks like:
>mode,zm
>type,common
#include "zm_mod.class"
///////////////////////////////////////////////////////////////////////////////////////////////////////////
rawfile,dummy.cfg
///////////////////////////////////////////////////////////////////////////////////////////////////////////
scriptparsetree,scripts/zm/gametypes/_clientids.gsc
scriptparsetree,scripts/zm/gametypes/_zm_perk_widows_wine.gsc
scriptparsetree,scripts/zm/gametypes/_zm_powerup_full_ammo.gsc
I don't have the carpenter one in there right now for the same reason that it is commented out on my main file.
If anyone can help me prevent these crashes as well as get the features working, I would greatly appreciate it!
Thank you.
Spiki:
How does it crash. Kick to main menu, console popup, game closes...
Atchfam77:
How does it crash. Kick to main menu, console popup, game closes...
Spiki:
For one I don't see the riotshield scripts in your zone file so they're not being loaded in
and anyway the riotshield is in core_patch.csv so you need to comment those lines.
So that basically solves your popup.
As for the ammo and carpenter idk.
Btw the 100s of lines of missing assets is ok. Protip: i think launching the game and map in developer 2 spits out the bad script / line number
Atchfam77:
For one I don't see the riotshield scripts in your zone file so they're not being loaded in
and anyway the riotshield is in core_patch.csv so you need to comment those lines.
So that basically solves your popup.
As for the ammo and carpenter idk.
Btw the 100s of lines of missing assets is ok. Protip: i think launching the game and map in developer 2 spits out the bad script / line number
Atchfam77:
Woah, a new thing happened.
I included both
scriptparsetree,scripts/zm/_zm_weap_riotshield.gsc
scriptparsetree,scripts/zm/gametypes/_zm_weap_riotshield.gsc
in my zone file, and now instead of getting a console popup and making me close my game, loading Moon in developer 2 kicks me to the main menu. It told me this:
"Server Disconnected: Clientfield mismatch"
"Check host TTY output"
Any ideas on what I'm supposed to do now, besides fixing the core patch line? I'm not sure what the TTY output is.
Spiki:
Woah, a new thing happened.
I included both
scriptparsetree,scripts/zm/_zm_weap_riotshield.gsc
scriptparsetree,scripts/zm/gametypes/_zm_weap_riotshield.gsc
in my zone file, and now instead of getting a console popup and making me close my game, loading Moon in developer 2 kicks me to the main menu. It told me this:
"Server Disconnected: Clientfield mismatch"
"Check host TTY output"
Any ideas on what I'm supposed to do now, besides fixing the core patch line? I'm not sure what the TTY output is.
Atchfam77:
you need to put in .csc too...
and .gsh if it exists just to be sure
Atchfam77:
you need to put in .csc too...
and .gsh if it exists just to be sure
tmk_boi:
Alright Spiki, I have an update for you: The Giant and Moon now boot me to the main menu citing a Server Client mismatch. How exactly do I make that fix for the core_patch? I'm not sure how to include that in the zone file.
Atchfam77:
scriptparsetree,zone_source\all\assetlist\core_patch.csv
Spiki:
scriptparsetree,zone_source\all\assetlist\core_patch.csv
Atchfam77:
I ended up getting it to work on Origins and the DLC maps. Some custom maps work but not all. I ended up releasing a version that doesn't include the carpenter script for more broad use.
\end thread