Neat mode! These days we're trying to keep the official modes rather straightforward and simple, so a fancy mode like this doesn't quite fit in our schema. However, I'm sure there are a large number of community server owners who would love a mode like this, so releasing it as community content when it's done would no doubt get it lots of attention.
Also, if you've got any interest in level design it feels like this mode would really benefit from some custom maps geared around it. Would perhaps need to be a bit grander in scale but would certainly enhance that single player experience you're going for.
Anyway, as for your questions:
-how to disable team selection so I can force a player to a specific team? Right now I implemented a custom solution which works, but it's not ideal;
Hate to say it but this just isn't supported yet, I'll add it to 5.1's todo list.
-how to get if a player hit (not killed) another one? I need it to register who hit the MI6 agent and survived when he died, so I can reward him with one more point;
def CalculateCustomDamage( self, victim, info, health, armour ):
if victim == None:
return health, armour
killer = GEPlayer.ToMPPlayer( info.GetAttacker() )
# Do stuff with killer/victim here.
# Be sure to return health, armour or modified values for them as this callback overrides the damage dealt
# by every damage event.
-how to force the radar off? I tried using SetForceRadar(False), but it doesn't seem to make any difference;
Right now this is just done via the gameplay's config file, which is a file in the cfg directory called [name of gameplay].cfg
Copy ltk's or put "ge_allowradar 0" inside this file.
-how to prevent equipping (not picking up) a token? It's not only useless, but it uses a glitchy hand texture;
It's been a little while but I think if you pass team=Glb.TEAM_OBS as an argument to the token setup function it will register that only observers can pick it up. Generally though for objectives that aren't meant to be actually held by anyone, Capture Points are used. Check out modes like Uplink and Die Another Day for examples on how to use capture points in this fashion. You can spawn capture points on specific dying players, if you want them to "carry" the objective without actually having a token.
-how to prevent picking up specific characters? I used "SetExcludedCharacters("boris,female_scientist,jaws,mayday,mishkin,oddjob,ourumov,baron_samedi,valentin")", but some of them, like samedi, still show up;
This command wasn't originally meant to exclude so many characters, and sadly as a result is limited in how many it can block off. 5.1 will make it more flexible, and probably also include a way to just skip the character selection menu for modes where only one character is allowed for a given player. For now though you'll probably just have to let people pick their characters and reassign them if necessary.
-how to destroy tokens, rather than picking them up? This one's not actually necessary, but I think it would be a nice addition :D
Calling
GERules.GetTokenMgr().RemoveTokenEnt( token, False )
and then decreasing the desired count of that token type should do the trick.
Regardless, your mode is looking pretty interesting so far and I'm excited to see where you take it! Good work so far and let me know if you have any other questions. Also, feel free to use the community discord server if the response times around here aren't the best. We've mostly migrated to that platform but keep the forums around for things like announcements and community releases.
If you assign the token to a team other than the one the destroying player is on, you should be able to use this callback to detect touches:
def OnEnemyTokenTouched( self, token, player ):
Otherwise I think
def CanPlayerHaveItem( self, player, item ):
can block token pickups if you check and see if the name of the item is "weapon_token", delete it, and return false.
Anyway, gamemodes are indeed entirely server side, with the exception of text localization. Sadly custom gamemodes need to hardcode their strings in one language or use already existing ones in the localization files but outside of this they should be entirely self contained. Just post the gamemode's .py file and any custom AI files and that should be all you need.
As for posting the WIP version, I went ahead and moved this topic to the "Community Content" section, which is for discussing WIP content, so feel free to just post it here. "Community Releases" is for the final release of a given piece of content, so be sure to make a new topic there when you feel the first version of the mode is finished. I'm looking forward to playing this!
def CalculateCustomDamage( self, victim, info, health, armor ):
killer = GEPlayer.ToMPPlayer(info.GetAttacker())
killerid = GEEntity.GetUniqueId(GEPlayer.ToMPPlayer(info.GetAttacker()))
target = GEEntity.GetUniqueId(victim)
damage = health + armor
damageMultiplier = 2
damage = damage * damageMultiplier
armor = damage # Can go way over the actual amount of armor the victim has but that's fine
health = max(damage - victim.GetArmor(), 0) # Make sure we don't add health if the victim's armor is enough to absorb the attack
# Return the adjusted damage values to the victim's health and armor gauges.
return health, armor
This should more or less be what you need, it's a little unintuitive to use for raw damage scaling since you control the health and armor damages separately instead of just modifying damage, but once you have the basic structure it's not too hard to make adjustments. I might make a utility function for 5.1 to make this a bit easier in the future, but for now you should be able to just modify this code however you need.
Regardless, I'm looking forward to trying out the new version of your mode tonight! We'll start playing in around 5-6 or so hours between 8:00 PM or 9:00 PM EST on Entropy-Server, so if you get a chance to stop by let me know and we'll play a few rounds together. Hope to see you there!
As for the looping alarm, you can either make a custom version of the sound that doesn't loop or stop it after a certain amount of time with:
StopSound( None, [SOUNDNAME] )
I just tried, but it's hopeless, it doesn't stop playing anyway! I'm exasperated! :D
def AlarmSet(self, newOn):
if newOn:
self.alarmT = 3.0
if self.alarmOn==False:
for playerI in GetPlayers():
GEUtil.PlaySoundTo(playerI, self.TOKEN_ALARM_SOUND)
else:
for playerI in GetPlayers():
GEUtil.StopSound(playerI, self.TOKEN_ALARM_SOUND)
print("GEUtil.StopSound("+playerI.GetCleanPlayerName()+", self.TOKEN_ALARM_SOUND)")
self.alarmOn = newOn
See the attachment for more.
UPDATE: I also just tried using "None" to target all players: same result :(
I found the problem ....
The ooagent.cfg file is set to ge_teamautobalance false, while the correct one would be ge_teamautobalance 0. After the fix, everything is fine now.
Thank you John!
I'll include your fix, though I'm a bit confused, since https://wiki.geshl2.com/goldeneye/server/cmds says it should be bool (true/false).
:) Thank you for playing.