======================================================================== Battlefield 2™ Gameplay Scripting Guide v0.1 May 25th 2005 Author: Joakim Lord ======================================================================== ======================================================================== This file contains information on the custom gameplay scripting system in Battlefield 2. ======================================================================== ======================================================================== 1. Introduction ======================================================================== In Battlefield 2, the overhead game logic is executed as python script. This script code is exposed as is in the game files, allowing mods to modify most of the game rules, such as scoring and gamemode. Python is a third party scripting language, which has been incorporated in the game engine. The version used is 2.3.4. The python documentation can be found at http://docs.python.org/index.html ======================================================================== 2. Features ======================================================================== * Trapping game events of many kinds, triggering custom actions. * Access to most functions in the python scripting language. Included modules are listed in section 8.1. * Wide accessibility to in-game objects, vehicles and players. * File handling permitted, allowing for example custom logging. ======================================================================== 3. Modifying gameplay scipts ======================================================================== The game logic scripts can be found here: /python/bf2 (global scripts) /mods/bf2/python (mod-specific scripts) To create custom gameplay scripts for your mod: * Copy the folder and content of mods/bf2/python into your mod directory. * Edit python scripts in these files. If you add a new gamemode, add the corresponding script file in game/gamemodes. (eg gpm_mymode.py) * When running the mod, these scripts will now be run instead of the ones in mods/bf2/python. * If you create a new python file which is not replacing an old file, or is a new game mode file, it has to be imported from a file that IS run. * To use a custom mod, use +modPath "mods/mymod" on the bf2_r.exe command line. * To use a custom game mode use +gameMode gpm_mymode (only valid using debug .exe). ======================================================================== 4. Debugging scripts ======================================================================== To use these features, the game has to be run with the debug .exe file. * In bf2, python is only run on the server. The clients know nothing about python or the scripts. * Standard output is mapped to the console window and the debug log, so any print-statements you make show up there. * You don’t have to restart the game to change the scripts, just resave the script file and type in the console: pythonHost.reinitialize. That re-parses all the scripts and re-implements the logic. So it’s actually possible to change game-logic on the fly, even with clients connected. * If you made any syntax errors in the scripts, an error will be displayed in the log. Sometimes it only shows up in Log_Server.log and not in debug_server.log though! This happens if the error occurs when the script is loading (ie. An indent-error breaking the parsing). The scripts are not compiled so only the basic syntax is checked in parse time, the rest of the errors occur in run-time. * Tip: Use debug.flushLog in the console to make sure the logs are written before examining them. * There is a flag called g_debug in bf2/bin/python/bf2/init.py, set that to 1 to enable full debug-output. ======================================================================== 5. Basic functionality ======================================================================== This section gives an overview of the functionality accessible by scripts. 5.1. TRAPPING GAME EVENTS A selection of game events are broadcasted to the scripting system, and are available for trapping. To capture an event, it has to be registered with the script. This is done with the function bf2.registerHandler. As soon as the call to registerhandler is made, the specified python function will start receiving callbacks when the event is trigger in the game. The callback function will be supplied with different arguments, depending on the event, and these have to be matched in the function header. The complete list of events and arguments are listed in section 7.9. Example: init(): bf2.registerHandler('PlayerRevived', onPlayerRevived) print "MyScript is now listening for players being revived..." onPlayerRevived(attacker, victim): #show in log print victim.getName(), " was revived by player ", attacker.getName(), "!" 5.2. AFFECTING THE GAME FROM SCRIPTS To make things happen in the game, a selection of methods have been exposed to the scripts. The python accessor for the game interface is the module 'host'. Most, but not all, of these functions are also wrapped in python, in the files PlayerManager.py, ObjectManager.py etc, for simplified syntax. Extending the previous example: onPlayerRevived(attacker, victim): # show in log print victim.getName(), " was revived by player ", attacker.getName(), "!" vehicle = victim.getVehicle() # Get the soldier-object for the player that was revived vehicle.setPosition(0, 90, 0) # Move him to map position 0,0, 90 meters up in the air. 5.3. WRAPPED OBJECTS The entities "objects" and "players" are wrapped against their real game-engine objects when sent to the scripts. Player refers to the actual player being connected in a game. The player has a name, a profile id and score. The player is not necessarily spawned in and playing the game, it still exists when dead or while just flying around with a camera watching. Players have an id between 0 and 255, where 255 is always the local player at the server, when running a non-dedicated server. Objects are what makes up all the vehicles, buildings, effects and more. Even the soldier, which the player controls, is an object. Objects have a position and different properties depending on object type. All objects in the game also has an object template, in which all its default properties are specified. Objects can have other objects attached to them, which are refered to as children. 5.4. ROUND SEQUENCE Besides regular game events, scripts can listen to events concerning the round state. This is done by registring a game status handler. Example: init(): bf2.registerGameStatusHandler('GameStatusChanged', onGameStatusChanged) onGameStatusChanged(status): if status == gameStatus.endgame: # show in log print "Game ended." The game status sequence for a regular round is always the same. There is no difference made between starting a new round on the same map, and loading a new map. The order in which the round-state specific calls are made looks like this: GameStatus Pregame Reset if new map, waiting for map to finish loading ... GameStatus Playing waiting for players... players are allowed to spawn and run around, but most game events are not triggered (see registerhandler in section 7.1) GameStatus Pregame Reset GameStatus Playing regular gameplay... round ends GameStatus Endgame end of round screen... next round starts, back to top 5.5. HELPER CLASSES A Timer is a helper class that will set up a call to a specified python method after a specified time. See section 7.7. A Trigger is a helper class that will call a specified python method whenever a player passes a specified boundary in the map. This is used by control points to trigger the flag takeovers. See section 7.8. ======================================================================== 6. Performance issues ======================================================================== Don't do heavy calculations or trigger things in short (per-frame) intervals. Server performance will drop significantly as python is not effective in these tasks. ======================================================================== 7. Interface Reference ======================================================================== This section lists the interface accessible from the scripts. For exact arguments and return types to these functions, and usage examples, see game python files. 7.1. MAIN METHODS registerHandler triggers a callback to the specified function whenever the specified event happens, supplying event-specific arguments does not trigger in pre/postgame unless alwaystrigger is set registerGameStatusHandler triggers a callback to the specified function whenever the game status changes, supplying the new gamestatus as argument endgame ends the current game, with the specified team as winner by specified victorytype 7.2. OBJECT METHODS hasArmor 0/1 depending on if object has an armor components isPlayerControlObject 0/1 depending on if object is a playercontrolobject isControlPoint 0/1 depending on if object is a controlpoints getPosition gets the objects world position setPosition sets the objects world position getRotation gets the objects own-axis rotation in degrees setRotation sets the objects own-axis rotation in degrees getChildren returns a python list with the child-objects to this object getParent returns the objects parent object, if any getTemplateProperty returns the value of the template parameter specified (as string), from this objects template Armored objects only: getDamage returns the health points for this object setDamage sets the health points for this object Player control objects only: getOccupyingPlayers returns a python list with the player(s) occupying this pco getIsRemoteControlled 0/1 depending on if object is remote-controlled getIsWreck 0/1 depending on if object is at wreck-state Controlpoints only: team returns the team number owning this control point, or 0 for neutral flag returns which team flag is visible on this control point, or 0 for neutral takeOverChangePerSecond returns the speed of which the flag is hoisting (positive) or lowering (negative) allowCaptureByTeam returns whether specified team can capture this control point 7.3. FUNCTIONS FROM OBJECTMANAGER.PY getObjectsOfType returns all objects currently in world with a certain class id getObjectsOfTemplate returns all objects currently in world, with a certain template name 7.4. PLAYER METHODS isValid 0/1 depending on if player still exists isRemote 0/1 depending on if player is a remote client, or player is connected from server isAIPlayer 0/1 depending on if player is an AI bot isAlive 0/1 depending on if player is alive isManDown 0/1 depending on if player is in man down state isConnected 0/1 depending on if player is still connected getProfileId returns players profile id getAddress returns players internet address getTeam returns players team setTeam sets players team getPing returns players current latency in ms getTimeToSpawn returns time until player can spawn setTimeToSpawn sets time until player can spawn getSquadId returns players squad id isSquadLeader 0/1 depending on if player is squad leader isCommander 0/1 depending on if player is commander getName returns players name setName sets players name getSpawnGroup returns players currently selected spawngroup setSpawnGroup sets players currently selected spawngroup getKit returns players kit getVehicle returns players current vehicle getDefaultVehicle returns players soldier-vehicle getPrimaryWeapon returns players currently wielded weapon 7.5. FUNCTIONS FROM PLAYERMANAGER.PY getNumberOfPlayers returns current number of players getCommander returns commander for specified team, if any getPlayers returns a list of all current players getPlayerByIndex returns the player with the specified id, if existing getNextPlayer returns the next player after specified player id. useful for timeslicing player updates. getNumberOfPlayersInTeam returns current number of players on specified team getNumberOfAlivePlayersInTeam returns current number of spawned in players on specified team enableScoreEvents enables score events again after being disabled disableScoreEvents disabled score events 7.6. FUNCTIONS FROM GAMELOGIC.PY getModDir get current mod directory, relative bf root (eg. mods/mymod/) getMapName get current mapname getWorldSize get current world size in meter getTeamName get team name for specified team isAIGame 0/1 depending on if game has AI enabled sendServerMessage sends text message to specific player, or to all players (playerId = -1) getTicketState return current ticket state for specified team setTicketState set ticket state for specified team getTickets returns current number of tickets for specified team setTickets sets number of tickets for specified team getDefaultTickets returns default tickets for current map for specified team getTicketChangePerSecond returns current ticketloss for specified team setTicketChangePerSecond sets ticketlossfor specified team getTicketLimit returns ticket limit with specified id, for team setTicketLimit sets a ticket limit with specified id, for team getDefaultTicketLossPerMin get ticket loss modifier for team getDefaultTicketLossAtEndPerMin set end ticket loss modifier getWinner returns winning team (only applicable at endgame) getVictoryType returns a number corresponing the victory type setHealPointLimit set heal amount in percent required for PlayerHealPoint callback setRepairPointLimit set repair amount in percent required for PlayerRepairPoint callback setGiveAmmoPointLimit set give-ammo amount in percent required for PlayerAmmoPoint callback setTeamDamagePointLimit set team damage amount in percent required for PlayerTeamDamagePoint callback setTeamVehicleDamagePointLimit set team vehicle damage amount in percent required for PlayerTeamVehicleDamagePoint callback ss_getParam get value from serversettings 7.7. TIMER FUNCTIONS Timer() (class constructor) registers timer which will call the specified callback function every seconds, with as an argument destroy removes timer getTime returns time for next triggering setTime sets time for next triggering setRecurring makes timer trigger continously with specified interval 7.8. TRIGGER FUNCTIONS createRadiusTrigger creates a spherical trigger, calling the specified callback function whenever a player passes through the boundary specified by and the position of , to where the trigger is attached, with as an argument createHemiSphericalTrigger same as createRadiusTrigger, except that the boundary is a circle aligned with the ground instead of a sphere destroyAllTriggers destroys all registered triggers destroy destroys specified trigger getObjects returns a tuple containing all the objects currently in the specified trigger boundary 7.9. EVENTS GENERATED FROM GAME Event id Arguments Triggered when -------- --------- -------------- PlayerKilled victim, attacker, weapon, assists, vehicle a player is killed (before man-down) PlayerRevived victim, attacker a player is revived PlayerDeath victim, vehicle player dies (after man-down) PickupKit player, kit player picks up kit DropKit player, kit player drops kit PlayerChangeWeapon player, oldweapon, newweapon player changes weapon PlayerChangeTeams player player changes teams PlayerChangedSquad player, oldsquad, newsquad player changes squad ChangedCommander team, oldcommander, newcommander team changes commander ChangedSquadLeader squad, oldsquadleader, newsquadleader squad changes squadleader. PlayerConnect player player connects to server PlayerDisconnect player player disconnects from server PlayerBanned player player is banned PlayerKicked player player is kicked EnterVehicle player, vehicle, childsoldieractive player enters vehicle. childsoldieractive is set if the position is open. ExitVehicle player, vehicle player exits vehicle PlayerSpawn player, startvehicle player spawns ControlPointChangedOwner controlpoint, takeover controlpoint changed team TicketLimitReached team, limitid a pre-set ticket limit was reached TimeLimitReached serversettings time limit was reached PlayerScore player, scoredifference player got score PlayerRepairPoint player, object player has repaired set limit amount PlayerHealPoint player, object player has healed set limit amount PlayerGiveAmmoPoint player, object player has given out ammo to set limit amount PlayerTeamDamagePoint player, object player has team damaged to set limit amount ConsoleSendCommand command, arg1, ... , arg4 a server command was issued using pythonHost.sendCommand ClientCommand command, player, args a client command was issued using gameLogic.remoteCommand RemoteCommand playerid, command rcon command issued ChatMessage player, text, channel chat message issued Reset round was reset ======================================================================== 8. Python modules reference ======================================================================== This section describes specifics of the Battlefield 2 python implementation. 8.1. PYTHON MODULES INCLUDED al array audioop binascii bsddb bz2 cd cmathmodule cPickle crypt cStringIO datetime dbm dl errno fcntl fl fm fpectl gc gdbm gl grp imageop imgfile itertools math md5 mmap nis operator os ossaudiodev parser posix pwd readline resource rgbimg select sha signal socket struct sunaudiodev syslog termios thread time unicodedata zlib ======================================================================== 9. Useful Web Sites ======================================================================== Python documentation: http://www.python.org/doc/ The Official Battlefield 2 Website: http://battlefield2.ea.com Check here for the latest news. Digital Illusions: http://www.dice.se The Developer's homepage. ======================================================================== DICE Copyright Copyright © 2005 Digital Illusions CE AB. ALL RIGHTS RESERVED. ========================================================================