added more games and maps

This commit is contained in:
Ayush Saini 2022-07-17 13:36:13 +05:30
parent d05c5bee29
commit 2f0773c2c9
33 changed files with 8913 additions and 798 deletions

View file

@ -48,7 +48,7 @@ max_party_size: 6
# playlist editor in the regular version of the game.
# This will give you a numeric code you can enter here to host that
# playlist.
playlist_code: 347990
playlist_code: 374313
# Alternately, you can embed playlist data here instead of using codes.
# Make sure to set session_type to the correct type for the data here.

1
dist/ba_root/.bsuuid vendored Normal file
View file

@ -0,0 +1 @@
b6b895e7-a2f9-45f1-b080-25806a8bfca9

View file

@ -1,736 +1,42 @@
{
"Achievements": {
"Boom Goes the Dynamite": {
"Complete": false
},
"Boxer": {
"Complete": false
},
"Dual Wielding": {
"Complete": false
},
"Flawless Victory": {
"Complete": false
},
"Free Loader": {
"Complete": false
},
"Gold Miner": {
"Complete": false
},
"Got the Moves": {
"Complete": false
},
"In Control": {
"Complete": false
},
"Last Stand God": {
"Complete": false
},
"Last Stand Master": {
"Complete": false
},
"Last Stand Wizard": {
"Complete": false
},
"Mine Games": {
"Complete": true
},
"Off You Go Then": {
"Complete": true
},
"Onslaught God": {
"Complete": false
},
"Onslaught Master": {
"Complete": false
},
"Onslaught Training Victory": {
"Complete": true
},
"Onslaught Wizard": {
"Complete": false
},
"Precision Bombing": {
"Complete": false
},
"Pro Boxer": {
"Complete": false
},
"Pro Football Shutout": {
"Complete": false
},
"Pro Football Victory": {
"Complete": false
},
"Pro Onslaught Victory": {
"Complete": false
},
"Pro Runaround Victory": {
"Complete": false
},
"Rookie Football Shutout": {
"Complete": false
},
"Rookie Football Victory": {
"Complete": false
},
"Rookie Onslaught Victory": {
"Complete": true
},
"Runaround God": {
"Complete": false
},
"Runaround Master": {
"Complete": false
},
"Runaround Wizard": {
"Complete": false
},
"Sharing is Caring": {
"Complete": false
},
"Stayin' Alive": {
"Complete": false
},
"Super Mega Punch": {
"Complete": false
},
"Super Punch": {
"Complete": true
},
"TNT Terror": {
"Complete": false
},
"Team Player": {
"Complete": true
},
"The Great Wall": {
"Complete": false
},
"The Wall": {
"Complete": false
},
"Uber Football Shutout": {
"Complete": false
},
"Uber Football Victory": {
"Complete": false
},
"Uber Onslaught Victory": {
"Complete": false
},
"Uber Runaround Victory": {
"Complete": false
}
},
"Auto Account State": "Server",
"Auto Balance Teams": true,
"Bear Coin": 814,
"Bear Store": {
"Buy Firebombs": false,
"Buy Option": false,
"Buy Percentage": false,
"Promo Code": {
"B-0mB3RYT2z": [
true,
910
],
"B-Asd14mON9G0D": [
true,
910
],
"D-rAcK0cJ23": [
true,
910
],
"E-Am54igO42Os": [
true,
600
],
"E-M4uN3K34XB": [
true,
840
],
"E-a27ZO6f3Y": [
true,
600
],
"G-Am54igO42Os": [
true,
1100
],
"P-tRo8nM8dZ": [
true,
2800
],
"PM-731ClcAF": [
true,
50000
],
"Y-tU2B3S": [
true,
500
]
}
},
"Campaigns": {
"Easy": {
"Onslaught Training": {
"Complete": true,
"High Scores": {
"1 Player": [
[
286,
{
"players": [
{
"character": "Spaz",
"name": "smoothie"
}
]
}
],
[
261,
{
"players": [
{
"character": "Spaz",
"name": "smoothie"
}
]
}
],
[
239,
{
"players": [
{
"character": "Spaz",
"name": "smoothie"
}
]
}
],
[
49,
{
"players": [
{
"character": "Spaz",
"name": "smoothie"
}
]
}
],
[
46,
{
"players": [
{
"character": "Spaz",
"name": "smoothie"
}
]
}
],
[
28,
{
"players": [
{
"character": "Spaz",
"name": "smoothie"
}
]
}
],
[
5,
{
"players": [
{
"character": "Spaz",
"name": "smoothie"
}
]
}
],
[
5,
{
"players": [
{
"character": "Spaz",
"name": "smoothie"
}
]
}
],
[
5,
{
"players": [
{
"character": "Spaz",
"name": "smoothie"
}
]
}
],
[
5,
{
"players": [
{
"character": "Spaz",
"name": "smoothie"
}
]
}
]
]
},
"Rating": 10.0
},
"Rookie Onslaught": {
"Complete": false,
"High Scores": {
"1 Player": [
[
297,
{
"players": [
{
"character": "Spaz",
"name": "smoothie"
}
]
}
],
[
34,
{
"players": [
{
"character": "Spaz",
"name": "smoothie"
}
]
}
]
]
},
"Rating": 10.0
}
}
},
"Custom Team Colors": [
[
2.0,
0.25,
1.0
],
[
1.0,
0.25,
0.2
]
],
"Custom Team Names": [
"ladoo",
"barfi"
],
"Default Player Profiles": {
"Client Input Device #1": "_random",
"Client Input Device #2": "__account__"
},
"Free-for-All Playlist Randomize": true,
"Free-for-All Playlist Selection": "__default__",
"Free-for-All Playlists": {
"Just Death Match": [
{
"settings": {
"Epic Mode": false,
"Kills to Win Per Player": 10,
"Respawn Times": 1.0,
"Time Limit": 300,
"map": "Doom Shroom"
},
"type": "bs_death_match.DeathMatchGame"
},
{
"settings": {
"Epic Mode": false,
"Kills to Win Per Player": 10,
"Respawn Times": 1.0,
"Time Limit": 300,
"map": "Crag Castle"
},
"type": "bs_death_match.DeathMatchGame"
}
],
"My Free-for-All Playlist": [
{
"settings": {
"Allow Negative Scores": false,
"Epic Mode": false,
"Kills to Win Per Player": 5,
"Respawn Times": 1.0,
"Time Limit": 0,
"map": "Courtyard"
},
"type": "bastd.game.deathmatch.DeathMatchGame"
}
]
},
"Idle Exit Minutes": null,
"Local Account Name": "Server3258837",
"PPM Settings": {
"Healing Damage PTG": 72,
"Powers Gravity": true,
"Powerup Name": true,
"Powerup Scale": 1.0,
"Powerup Style": "Auto",
"Powerup Time": false,
"Powerup With Shield": true,
"Powerups": {
"Curse": 1,
"Fire Bombs": 3,
"Fly Bombs": 3,
"Goodbye": 2,
"Healing Damage": 1,
"Health": 1,
"Ice Bombs": 3,
"Ice Man": 1,
"Impact Bombs": 3,
"Impairment Bombs": 2,
"Mine Bombs": 2,
"Punch": 3,
"Shield": 2,
"Speed": 2,
"Sticky Bombs": 3,
"Tank Shield": 1,
"Triple": 3
},
"Tank Shield PTG": 96
},
"Player Profiles": {
"__account__": {
"character": "Spaz",
"color": [
0.5,
0.25,
1.0
],
"highlight": [
0.5,
0.25,
1.0
]
}
},
"Plugins": {
"plugins.Init": {
"enabled": true
}
},
"Port": 43210,
"Region Pings": {
"af-south-1": 328.2357999996748,
"ap-northeast-1": 150.0941541948123,
"ap-northeast-2": 160.2201884064998,
"ap-south-1": 45.05286179925315,
"ap-southeast-1": 101.91129060697858,
"ap-southeast-2": 183.6228000029223,
"ca-central-1": 262.4569968022115,
"eu-central-1": 155.88790780561976,
"eu-north-1": 181.94498299446423,
"eu-south-1": 156.48616400256287,
"eu-west-1": 179.42955539320246,
"eu-west-2": 158.43393659518915,
"eu-west-3": 170.620519401622,
"me-south-1": 78.16982959693996,
"sa-east-1": 345.57150000182446,
"us-east-1": 238.92560360513744,
"us-east-2": 257.30932620124076,
"us-west-1": 255.34800000605173,
"us-west-2": 292.9734999925131
},
"Selected Coop Game": "Easy:Rookie Onslaught",
"Show Tutorial": false,
"Signed In Last Session": false,
"Team Game Max Player": 25,
"Team Game Max Players": 25,
"Free-for-All Max Players":25,
"Team Tournament Playlist Randomize": true,
"Team Tournament Playlist Selection": "My Teams Playlist",
"Team Tournament Playlists": {
"My Teams Playlist": [
{
"settings": {
"Epic Mode": false,
"Kills to Win Per Player": 1,
"Respawn Times": 1.0,
"Time Limit": 0,
"map": "Doom Shroom"
},
"type": "bastd.game.deathmatch.DeathMatchGame"
}
],
"My Teams Playlist 2": [
{
"settings": {
"Epic Mode": false,
"Kills to Win Per Player": 5,
"Respawn Times": 1.0,
"Time Limit": 0,
"map": "Happy Thoughts"
},
"type": "bastd.game.deathmatch.DeathMatchGame"
}
],
"\u041a\u043e\u043f\u0438\u044f \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u043b\u0435\u0439-\u043b\u0438\u0441\u0442 \u0440\u0435\u0436\u0438\u043c\u0430 \u041a\u043e\u043c\u0430\u043d\u0434\u044b": [
{
"settings": {
"Epic Mode": false,
"Flag Idle Return Time": 30,
"Flag Touch Return Time": 0,
"Respawn Times": 1.0,
"Score to Win": 3,
"Time Limit": 600,
"map": "Bridgit"
},
"type": "bsCaptureTheFlag.CTFGame"
},
{
"settings": {
"Epic Mode": false,
"Respawn Times": 1.0,
"Score to Win": 3,
"Time Limit": 600,
"map": "Step Right Up"
},
"type": "bsAssault.AssaultGame"
},
{
"settings": {
"Balance Total Lives": false,
"Epic Mode": false,
"Lives Per Player": 3,
"Respawn Times": 1.0,
"Solo Mode": true,
"Time Limit": 600,
"map": "Rampage"
},
"type": "bsElimination.EliminationGame"
},
{
"settings": {
"Epic Mode": false,
"Kills to Win Per Player": 5,
"Respawn Times": 1.0,
"Time Limit": 300,
"map": "Roundabout"
},
"type": "bsDeathMatch.DeathMatchGame"
},
{
"settings": {
"Respawn Times": 1.0,
"Score to Win": 1,
"Time Limit": 600,
"map": "Hockey Stadium"
},
"type": "bsHockey.HockeyGame"
},
{
"settings": {
"Hold Time": 30,
"Respawn Times": 1.0,
"Time Limit": 300,
"map": "Monkey Face"
},
"type": "bsKeepAway.KeepAwayGame"
},
{
"settings": {
"Balance Total Lives": false,
"Epic Mode": true,
"Lives Per Player": 1,
"Respawn Times": 1.0,
"Solo Mode": false,
"Time Limit": 120,
"map": "Tip Top"
},
"type": "bsElimination.EliminationGame"
},
{
"settings": {
"Epic Mode": false,
"Respawn Times": 1.0,
"Score to Win": 3,
"Time Limit": 300,
"map": "Crag Castle"
},
"type": "bsAssault.AssaultGame"
},
{
"settings": {
"Epic Mode": false,
"Kills to Win Per Player": 5,
"Respawn Times": 1.0,
"Time Limit": 300,
"map": "Doom Shroom"
},
"type": "bsDeathMatch.DeathMatchGame"
},
{
"settings": {
"Epic Mode": false,
"map": "Rampage"
},
"type": "bsMeteorShower.MeteorShowerGame"
},
{
"settings": {
"Epic Mode": false,
"Flag Idle Return Time": 30,
"Flag Touch Return Time": 0,
"Respawn Times": 1.0,
"Score to Win": 2,
"Time Limit": 600,
"map": "Roundabout"
},
"type": "bsCaptureTheFlag.CTFGame"
},
{
"settings": {
"Respawn Times": 1.0,
"Score to Win": 21,
"Time Limit": 600,
"map": "Football Stadium"
},
"type": "bsFootball.FootballTeamGame"
},
{
"settings": {
"Epic Mode": true,
"Respawn Times": 0.25,
"Score to Win": 3,
"Time Limit": 120,
"map": "Bridgit"
},
"type": "bsAssault.AssaultGame"
},
{
"map": "Doom Shroom",
"settings": {
"Enable Impact Bombs": 1,
"Enable Triple Bombs": false,
"Target Count": 2,
"map": "Doom Shroom"
},
"type": "bsTargetPractice.TargetPracticeGame"
},
{
"settings": {
"Hold Time": 30,
"Respawn Times": 1.0,
"Time Limit": 300,
"map": "Tip Top"
},
"type": "bsKingOfTheHill.KingOfTheHillGame"
},
{
"settings": {
"Epic Mode": false,
"Respawn Times": 1.0,
"Score to Win": 2,
"Time Limit": 300,
"map": "Zigzag"
},
"type": "bsAssault.AssaultGame"
},
{
"settings": {
"Epic Mode": false,
"Flag Idle Return Time": 30,
"Flag Touch Return Time": 0,
"Respawn Times": 1.0,
"Score to Win": 3,
"Time Limit": 300,
"map": "Happy Thoughts"
},
"type": "bsCaptureTheFlag.CTFGame"
},
{
"settings": {
"Bomb Spawning": 1000,
"Epic Mode": true,
"Laps": 1,
"Mine Spawning": 2000,
"Time Limit": 300,
"map": "Big G"
},
"type": "bsRace.RaceGame"
},
{
"settings": {
"Epic Mode": false,
"Kills to Win Per Player": 5,
"Respawn Times": 1.0,
"Time Limit": 300,
"map": "Monkey Face"
},
"type": "bsDeathMatch.DeathMatchGame"
},
{
"settings": {
"Hold Time": 30,
"Respawn Times": 1.0,
"Time Limit": 300,
"map": "Lake Frigid"
},
"type": "bsKeepAway.KeepAwayGame"
},
{
"settings": {
"Epic Mode": false,
"Flag Idle Return Time": 30,
"Flag Touch Return Time": 3,
"Respawn Times": 1.0,
"Score to Win": 2,
"Time Limit": 300,
"map": "Tip Top"
},
"type": "bsCaptureTheFlag.CTFGame"
},
{
"settings": {
"Balance Total Lives": false,
"Epic Mode": false,
"Lives Per Player": 3,
"Respawn Times": 1.0,
"Solo Mode": false,
"Time Limit": 300,
"map": "Crag Castle"
},
"type": "bsElimination.EliminationGame"
},
{
"settings": {
"Epic Mode": true,
"Respawn Times": 0.25,
"Time Limit": 120,
"map": "Zigzag"
},
"type": "bsConquest.ConquestGame"
}
]
},
"launchCount": 252,
"lc14173": 1,
"lc14292": 1
}
"Achievements": {},
"Auto Account State": "Server",
"Auto Balance Teams": true,
"Campaigns": {},
"Custom Team Colors": [
[
2.0,
0.25,
1.0
],
[
1.0,
0.25,
0.2
]
],
"Custom Team Names": [
"ladoo",
"barfi"
],
"Fleet Zone Pings": {
"prod": {
"ap-northeast-1": 156.68950000008408,
"ap-northeast-2": 156.49900000016714,
"ap-south-1": 39.8473224001209,
"ap-southeast-1": 81.71677339999769,
"eu-north-1": 169.96319999998377,
"me-south-1": 69.94866120011193
}
},
"Free-for-All Playlists": {},
"Idle Exit Minutes": null,
"Player Profiles": {},
"Port": 43210,
"Show Tutorial": false,
"Signed In Last Session": false,
"Team Tournament Playlists": {},
"launchCount": 4,
"lc14173": 1,
"lc14292": 1
}

1
dist/ba_root/config.json.prev vendored Normal file
View file

@ -0,0 +1 @@
{"Achievements": {}, "Auto Account State": "Server", "Auto Balance Teams": true, "Campaigns": {}, "Custom Team Colors": [[2.0, 0.25, 1.0], [1.0, 0.25, 0.2]], "Custom Team Names": ["ladoo", "barfi"], "Fleet Zone Pings": {"prod": {"ap-northeast-1": 150.23180000025604, "ap-northeast-2": 165.59890000007726, "ap-south-1": 39.26117700029499, "ap-southeast-1": 84.0365405999919, "eu-north-1": 173.02299999983006, "me-south-1": 78.74480959990251}}, "Free-for-All Playlists": {}, "Idle Exit Minutes": null, "Player Profiles": {}, "Port": 43210, "Show Tutorial": false, "Signed In Last Session": false, "Team Tournament Playlists": {}, "launchCount": 3, "lc14173": 1, "lc14292": 1}

193
dist/ba_root/mods/games/ArmsRace.py vendored Normal file
View file

@ -0,0 +1,193 @@
#Ported by: Freaku / @[Just] Freak#4999
#Join BCS:
# https://discord.gg/ucyaesh
# ba_meta require api 6
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
from bastd.actor.playerspaz import PlayerSpaz
if TYPE_CHECKING:
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
class State:
def __init__(self, bomb=None, grab=False, punch=False, curse=False, required=False, final=False, name=''):
self.bomb = bomb
self.grab = grab
self.punch = punch
self.pickup = False
self.curse = curse
self.required = required or final
self.final = final
self.name = name
self.next = None
self.index = None
def apply(self, spaz):
spaz.disconnect_controls_from_player()
spaz.connect_controls_to_player(enable_punch=self.punch,
enable_bomb=self.bomb,
enable_pickup=self.grab)
if self.curse:
spaz.curse_time = -1
spaz.curse()
if self.bomb:
spaz.bomb_type = self.bomb
spaz.set_score_text(self.name)
def get_setting(self):
return (self.name)
states = [ State(bomb='normal', name='Basic Bombs'),
State(bomb='ice', name='Frozen Bombs'),
State(bomb='sticky', name='Sticky Bombs'),
State(bomb='impact', name='Impact Bombs'),
State(grab=True, name='Grabbing only'),
State(punch=True, name='Punching only'),
State(curse=True, name='Cursed', final=True) ]
class Player(ba.Player['Team']):
"""Our player type for this game."""
def __init__(self):
self.state = None
class Team(ba.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.score = 0
# ba_meta export game
class ArmsRaceGame(ba.TeamGameActivity[Player, Team]):
"""A game type based on acquiring kills."""
name = 'Arms Race'
description = 'Upgrade your weapon by eliminating enemies.\nWin the match by being the first player\nto get a kill while cursed.'
# Print messages when players die since it matters here.
announce_player_deaths = True
@classmethod
def get_available_settings(
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
settings = [
ba.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
('1 Minute', 60),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600),
('20 Minutes', 1200),
],
default=0,
),
ba.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
('Short', 0.5),
('Normal', 1.0),
('Long', 2.0),
('Longer', 4.0),
],
default=1.0,
),
ba.BoolSetting('Epic Mode', default=False)]
for state in states:
if not state.required:
settings.append(ba.BoolSetting(state.get_setting(), default=True))
return settings
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return (issubclass(sessiontype, ba.DualTeamSession)
or issubclass(sessiontype, ba.FreeForAllSession))
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ba.getmaps('melee')
def __init__(self, settings: dict):
super().__init__(settings)
self.states = [s for s in states if settings.get(s.name, True)]
for i, state in enumerate(self.states):
if i < len(self.states) and not state.final:
state.next = self.states[i + 1]
state.index = i
self._dingsound = ba.getsound('dingSmall')
self._epic_mode = bool(settings['Epic Mode'])
self._time_limit = float(settings['Time Limit'])
# Base class overrides.
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
ba.MusicType.TO_THE_DEATH)
def get_instance_description(self) -> Union[str, Sequence]:
return 'Upgrade your weapon by eliminating enemies.'
def get_instance_description_short(self) -> Union[str, Sequence]:
return 'kill ${ARG1} enemies', len(self.states)
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self._time_limit)
# self.setup_standard_powerup_drops()
def on_player_join(self, player):
if player.state is None:
player.state = self.states[0]
self.spawn_player(player)
# overriding the default character spawning..
def spawn_player(self, player):
if player.state is None:
player.state = self.states[0]
super().spawn_player(player)
player.state.apply(player.actor)
def isValidKill(self, m):
if m.getkillerplayer(Player) is None:
return False
if m.getkillerplayer(Player).team is m.getplayer(Player).team:
return False
return True
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
if self.isValidKill(msg):
if not msg.getkillerplayer(Player).state.final:
msg.getkillerplayer(Player).state = msg.getkillerplayer(Player).state.next
msg.getkillerplayer(Player).state.apply(msg.getkillerplayer(Player).actor)
else:
msg.getkillerplayer(Player).team.score += 1
self.end_game()
self.respawn_player(msg.getplayer(Player))
else:
return super().handlemessage(msg)
return None
def end_game(self) -> None:
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)

515
dist/ba_root/mods/games/BigBall.py vendored Normal file
View file

@ -0,0 +1,515 @@
#Made by MythB
#Ported by: Freaku / @[Just] Freak#4999
# ba_meta require api 6
from __future__ import annotations
from typing import TYPE_CHECKING
import ba,random
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
from bastd.actor.powerupbox import PowerupBoxFactory
from bastd.gameutils import SharedObjects
from bastd.actor.flag import Flag
if TYPE_CHECKING:
from typing import Any, Sequence, Dict, Type, List, Optional, Union
class PuckDiedMessage:
"""Inform something that a puck has died."""
def __init__(self, puck: Puck):
self.puck = puck
#goalpost
class FlagKale(ba.Actor):
def __init__(self,position=(0,2.5,0),color=(1,1,1)):
super().__init__()
activity = self.getactivity()
shared = SharedObjects.get()
self.node = ba.newnode('flag',
attrs={'position':(position[0],position[1]+0.75,position[2]),
'color_texture':activity._flagKaleTex,
'color':color,
'materials':[shared.object_material,activity._kaleMaterial],
},
delegate=self)
def handleMessage(self,m):
if isinstance(m,ba.DieMessage):
if self.node.exists():
self.node.delete()
elif isinstance(m,ba.OutOfBoundsMessage):
self.handlemessage(ba.DieMessage())
else:
super().handlemessage(msg)
class Puck(ba.Actor):
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)):
super().__init__()
shared = SharedObjects.get()
activity = self.getactivity()
# Spawn just above the provided point.
self._spawn_pos = (position[0], position[1] + 1.0, position[2])
self.last_players_to_touch: Dict[int, Player] = {}
self.scored = False
assert activity is not None
assert isinstance(activity, BBGame)
pmats = [shared.object_material, activity.puck_material]
self.node = ba.newnode('prop',
delegate=self,
attrs={
'model': activity._ballModel,
'color_texture': activity._ballTex,
'body': 'sphere',
'reflection': 'soft',
'reflection_scale': [0.2],
'shadow_size': 0.8,
'is_area_of_interest': True,
'position': self._spawn_pos,
'materials': pmats,
'body_scale': 4,
'model_scale': 1,
'density': 0.02})
ba.animate(self.node, 'model_scale', {0: 0, 0.2: 1.3, 0.26: 1})
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
assert self.node
self.node.delete()
activity = self._activity()
if activity and not msg.immediate:
activity.handlemessage(PuckDiedMessage(self))
# If we go out of bounds, move back to where we started.
elif isinstance(msg, ba.OutOfBoundsMessage):
assert self.node
self.node.position = self._spawn_pos
elif isinstance(msg, ba.HitMessage):
assert self.node
assert msg.force_direction is not None
self.node.handlemessage(
'impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0],
msg.velocity[1], msg.velocity[2], 1.0 * msg.magnitude,
1.0 * msg.velocity_magnitude, msg.radius, 0,
msg.force_direction[0], msg.force_direction[1],
msg.force_direction[2])
# If this hit came from a player, log them as the last to touch us.
s_player = msg.get_source_player(Player)
if s_player is not None:
activity = self._activity()
if activity:
if s_player in activity.players:
self.last_players_to_touch[s_player.team.id] = s_player
else:
super().handlemessage(msg)
#for night mode: using a actor with large shadow and little model scale. Better then tint i think, players and objects more visible
class NightMod(ba.Actor):
def __init__(self,position=(0,0,0)):
super().__init__()
shared = SharedObjects.get()
activity = self.getactivity()
# spawn just above the provided point
self._spawnPos = (position[0],position[1],position[2])
self.node = ba.newnode("prop",
attrs={'model': activity._nightModel,
'color_texture': activity._nightTex,
'body':'sphere',
'reflection':'soft',
'body_scale': 0.1,
'model_scale':0.001,
'density':0.010,
'reflection_scale':[0.23],
'shadow_size': 999999.0,
'is_area_of_interest':True,
'position':self._spawnPos,
'materials': [activity._nightMaterial]
},
delegate=self)
def handlemssage(self,m):
super().handlemessage(m)
class Player(ba.Player['Team']):
"""Our player type for this game."""
class Team(ba.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.score = 0
# ba_meta export game
class BBGame(ba.TeamGameActivity[Player, Team]):
name = 'Big Ball'
description = 'Score some goals.\nFlags are goalposts.\nScored team players get boxing gloves,\nNon-scored team players getting shield (if Grant Powers on Score).\nYou can also set Night Mode!'
available_settings = [
ba.IntSetting(
'Score to Win',
min_value=1,
default=1,
increment=1,
),
ba.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
('1 Minute', 60),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600),
('20 Minutes', 1200),
],
default=0,
),
ba.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
('Short', 0.5),
('Normal', 1.0),
('Long', 2.0),
('Longer', 4.0),
],
default=1.0,
),
ba.BoolSetting('Epic Mode', True),
ba.BoolSetting('Night Mode', False),
ba.BoolSetting('Grant Powers on Score', False)
]
default_music = ba.MusicType.HOCKEY
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.DualTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ['Football Stadium']
def __init__(self, settings: dict):
super().__init__(settings)
shared = SharedObjects.get()
self._scoreboard = Scoreboard()
self._cheer_sound = ba.getsound('cheer')
self._chant_sound = ba.getsound('crowdChant')
self._foghorn_sound = ba.getsound('foghorn')
self._swipsound = ba.getsound('swip')
self._whistle_sound = ba.getsound('refWhistle')
self._ballModel = ba.getmodel("shield")
self._ballTex = ba.gettexture("eggTex1")
self._ballSound = ba.getsound("impactMedium2")
self._flagKaleTex = ba.gettexture("star")
self._kaleSound = ba.getsound("metalHit")
self._nightModel = ba.getmodel("shield")
self._nightTex = ba.gettexture("black")
self._kaleMaterial = ba.Material()
#add friction to flags for standing our position (as far as)
self._kaleMaterial.add_actions(conditions=("they_have_material",shared.footing_material),
actions=( ("modify_part_collision","friction",9999.5)))
self._kaleMaterial.add_actions(conditions=( ("we_are_younger_than",1),'and',
("they_have_material",shared.object_material)),
actions=( ("modify_part_collision","collide",False)))
self._kaleMaterial.add_actions(conditions=("they_have_material",shared.pickup_material),
actions=( ("modify_part_collision","collide",False)))
self._kaleMaterial.add_actions(
conditions=('they_have_material',shared.object_material),
actions=(('impact_sound',self._kaleSound,2,5)))
#we dont wanna hit the night so
self._nightMaterial = ba.Material()
self._nightMaterial.add_actions(conditions=(('they_have_material',shared.pickup_material),'or',
('they_have_material',shared.attack_material)),
actions=(('modify_part_collision','collide',False)))
# we also dont want anything moving it
self._nightMaterial.add_actions(
conditions=(('they_have_material',shared.object_material),'or',
('they_dont_have_material',shared.footing_material)),
actions=(('modify_part_collision','collide',False),
('modify_part_collision','physical',False)))
self.puck_material = ba.Material()
self.puck_material.add_actions(actions=(('modify_part_collision',
'friction', 0.5)))
self.puck_material.add_actions(conditions=('they_have_material',
shared.pickup_material),
actions=('modify_part_collision',
'collide', False))
self.puck_material.add_actions(
conditions=(
('we_are_younger_than', 100),
'and',
('they_have_material', shared.object_material),
),
actions=('modify_node_collision', 'collide', False),
)
self.puck_material.add_actions(conditions=('they_have_material',
shared.footing_material),
actions=('impact_sound',
self._ballSound, 0.2, 5))
# Keep track of which player last touched the puck
self.puck_material.add_actions(
conditions=('they_have_material', shared.player_material),
actions=(('call', 'at_connect',
self._handle_puck_player_collide), ))
# We want the puck to kill powerups; not get stopped by them
self.puck_material.add_actions(
conditions=('they_have_material',
PowerupBoxFactory.get().powerup_material),
actions=(('modify_part_collision', 'physical', False),
('message', 'their_node', 'at_connect', ba.DieMessage())))
self._score_region_material = ba.Material()
self._score_region_material.add_actions(
conditions=('they_have_material', self.puck_material),
actions=(('modify_part_collision', 'collide',
True), ('modify_part_collision', 'physical', False),
('call', 'at_connect', self._handle_score)))
self._puck_spawn_pos: Optional[Sequence[float]] = None
self._score_regions: Optional[List[ba.NodeActor]] = None
self._puck: Optional[Puck] = None
self._score_to_win = int(settings['Score to Win'])
self._time_limit = float(settings['Time Limit'])
self._nm = bool(settings['Night Mode'])
self._grant_power = bool(settings['Grant Powers on Score'])
self._epic_mode = bool(settings['Epic Mode'])
# Base class overrides.
self.slow_motion = self._epic_mode
def get_instance_description(self) -> Union[str, Sequence]:
if self._score_to_win == 1:
return 'Score a goal.'
return 'Score ${ARG1} goals.', self._score_to_win
def get_instance_description_short(self) -> Union[str, Sequence]:
if self._score_to_win == 1:
return 'score a goal'
return 'score ${ARG1} goals', self._score_to_win
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self._time_limit)
self.setup_standard_powerup_drops(enable_tnt = False)
self._puck_spawn_pos = self.map.get_flag_position(None)
self._flagKalesSpawn()
self._spawn_puck()
#for night mode we need night actor. And same goodies for nigh mode
if self._nm: self._nightSpawny(),self._flagKaleFlash()
# Set up the two score regions.
defs = self.map.defs
self._score_regions = []
self._score_regions.append(
ba.NodeActor(
ba.newnode('region',
attrs={
'position': (13.75, 0.85744967453, 0.1095578275),
'scale': (1.05,1.1,3.8),
'type': 'box',
'materials': [self._score_region_material]
})))
self._score_regions.append(
ba.NodeActor(
ba.newnode('region',
attrs={
'position': (-13.55, 0.85744967453, 0.1095578275),
'scale': (1.05,1.1,3.8),
'type': 'box',
'materials': [self._score_region_material]
})))
self._update_scoreboard()
ba.playsound(self._chant_sound)
def _nightSpawny(self):
self.MythBrk = NightMod(position=(0, 0.05744967453, 0))
#spawn some goodies on nightmode for pretty visuals
def _flagKaleFlash(self):
#flags positions
kale1 = (-12.45, 0.05744967453, -2.075)
kale2 = (-12.45, 0.05744967453, 2.075)
kale3 = (12.66, 0.03986567039, 2.075)
kale4 = (12.66, 0.03986567039, -2.075)
flash = ba.newnode("light",
attrs={'position':kale1,
'radius':0.15,
'color':(1.0,1.0,0.7)})
flash = ba.newnode("light",
attrs={'position':kale2,
'radius':0.15,
'color':(1.0,1.0,0.7)})
flash = ba.newnode("light",
attrs={'position':kale3,
'radius':0.15,
'color':(0.7,1.0,1.0)})
flash = ba.newnode("light",
attrs={'position':kale4,
'radius':0.15,
'color':(0.7,1.0,1.0)})
#flags positions
def _flagKalesSpawn(self):
for team in self.teams:
if team.id == 0:
_colorTeam0 = team.color
if team.id == 1:
_colorTeam1 = team.color
self._MythB = FlagKale(position=(-12.45, 0.05744967453, -2.075),color=_colorTeam0)
self._MythB2 =FlagKale(position=(-12.45, 0.05744967453, 2.075),color=_colorTeam0)
self._MythB3 =FlagKale(position=(12.66, 0.03986567039, 2.075),color=_colorTeam1)
self._MythB4 =FlagKale(position=(12.66, 0.03986567039, -2.075),color=_colorTeam1)
def on_team_join(self, team: Team) -> None:
self._update_scoreboard()
def _handle_puck_player_collide(self) -> None:
collision = ba.getcollision()
try:
puck = collision.sourcenode.getdelegate(Puck, True)
player = collision.opposingnode.getdelegate(PlayerSpaz,
True).getplayer(
Player, True)
except ba.NotFoundError:
return
puck.last_players_to_touch[player.team.id] = player
def _kill_puck(self) -> None:
self._puck = None
def _handle_score(self) -> None:
"""A point has been scored."""
assert self._puck is not None
assert self._score_regions is not None
# Our puck might stick around for a second or two
# we don't want it to be able to score again.
if self._puck.scored:
return
region = ba.getcollision().sourcenode
index = 0
for index in range(len(self._score_regions)):
if region == self._score_regions[index].node:
break
for team in self.teams:
if team.id == index:
scoring_team = team
team.score += 1
# tell scored team players to celebrate and give them to boxing gloves
if self._grant_power:
for player in team.players:
try: player.actor.node.handlemessage(ba.PowerupMessage('punch'))
except: pass
# Tell all players to celebrate.
for player in team.players:
if player.actor:
player.actor.handlemessage(ba.CelebrateMessage(2.0))
# If we've got the player from the scoring team that last
# touched us, give them points.
if (scoring_team.id in self._puck.last_players_to_touch
and self._puck.last_players_to_touch[scoring_team.id]):
self.stats.player_scored(
self._puck.last_players_to_touch[scoring_team.id],
100,
big_message=True)
# End game if we won.
if team.score >= self._score_to_win:
self.end_game()
else:
if self._grant_power:
for player in team.players:
try: player.actor.node.handlemessage(ba.PowerupMessage('shield'))
except: pass
ba.playsound(self._foghorn_sound)
ba.playsound(self._cheer_sound)
self._puck.scored = True
# Kill the puck (it'll respawn itself shortly).
ba.timer(1.0, self._kill_puck)
light = ba.newnode('light',
attrs={
'position': ba.getcollision().position,
'height_attenuated': False,
'color': (1, 0, 0)
})
ba.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
ba.timer(1.0, light.delete)
ba.cameraflash(duration=10.0)
self._update_scoreboard()
def end_game(self) -> None:
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)
def _update_scoreboard(self) -> None:
winscore = self._score_to_win
for team in self.teams:
self._scoreboard.set_team_value(team, team.score, winscore)
def handlemessage(self, msg: Any) -> Any:
# Respawn dead players if they're still in the game.
if isinstance(msg, ba.PlayerDiedMessage):
# Augment standard behavior...
super().handlemessage(msg)
self.respawn_player(msg.getplayer(Player))
# Respawn dead pucks.
elif isinstance(msg, PuckDiedMessage):
if not self.has_ended():
ba.timer(3.0, self._spawn_puck)
else:
super().handlemessage(msg)
def _flash_puck_spawn(self) -> None:
light = ba.newnode('light',
attrs={
'position': self._puck_spawn_pos,
'height_attenuated': False,
'color': (1, 0, 0)
})
ba.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True)
ba.timer(1.0, light.delete)
def _spawn_puck(self) -> None:
ba.playsound(self._swipsound)
ba.playsound(self._whistle_sound)
self._flash_puck_spawn()
assert self._puck_spawn_pos is not None
self._puck = Puck(position=self._puck_spawn_pos)
self._puck.light = ba.newnode('light',
owner=self._puck.node,
attrs={'intensity':0.3,
'height_attenuated':False,
'radius':0.2,
'color': (0.9,0.2,0.9)})
self._puck.node.connectattr('position',self._puck.light,'position')

227
dist/ba_root/mods/games/Bounty.py vendored Normal file
View file

@ -0,0 +1,227 @@
# Released under the MIT License. See LICENSE for details.
#
"""DeathMatch game and support classes."""
# ba_meta require api 6
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
if TYPE_CHECKING:
from typing import Any, Union, Sequence, Optional
class Player(ba.Player['Team']):
"""Our player type for this game."""
class Team(ba.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.score = 0
# ba_meta export game
class BountyGame(ba.TeamGameActivity[Player, Team]):
"""A game type based on acquiring kills."""
name = 'Bounty'
description = 'Score Maximum Stars To Win'
# Print messages when players die since it matters here.
announce_player_deaths = True
@classmethod
def get_available_settings(
cls, sessiontype: type[ba.Session]) -> list[ba.Setting]:
settings = [ba.IntChoiceSetting(
'Time Limit',
choices=[
('30 Seconds', 30),
('1 Minute', 60),
('1½ Minute', 90),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600)],
default=120,
),
ba.FloatChoiceSetting(
'Respawn Times',
choices=[
('Short', 0.5),
('Normal', 1.0),
('Long', 2.0),
('Longer', 4.0),
],
default=1.0,
),
ba.BoolSetting('Epic Mode', default=False),
]
# In teams mode, a suicide gives a point to the other team, but in
# free-for-all it subtracts from your own score. By default we clamp
# this at zero to benefit new players, but pro players might like to
# be able to go negative. (to avoid a strategy of just
# suiciding until you get a good drop)
if issubclass(sessiontype, ba.FreeForAllSession):
settings.append(
ba.BoolSetting('Allow Negative Scores', default=False))
return settings
@classmethod
def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool:
return (issubclass(sessiontype, ba.DualTeamSession)
or issubclass(sessiontype, ba.FreeForAllSession))
@classmethod
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
return ba.getmaps('melee')
def __init__(self, settings: dict):
super().__init__(settings)
self._scoreboard = Scoreboard()
self._score_to_win: Optional[int] = None
self._dingsound = ba.getsound('dingSmall')
self._epic_mode = bool(settings['Epic Mode'])
self._time_limit = float(settings['Time Limit'])
self._allow_negative_scores = bool(
settings.get('Allow Negative Scores', False))
# Base class overrides.
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
ba.MusicType.TO_THE_DEATH)
def get_instance_description(self) -> Union[str, Sequence]:
return 'Collect Stars of your enemies.'
def get_instance_description_short(self) -> Union[str, Sequence]:
return 'Collect Stars of your enemies.'
def on_team_join(self, team: Team) -> None:
if self.has_begun():
self._update_scoreboard()
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self._time_limit)
self.setup_standard_powerup_drops()
# Base kills needed to win on the size of the largest team.
self._update_scoreboard()
def spawn_player(self, player: Player) -> ba.Actor:
spaz = self.spawn_player_spaz(player)
assert spaz.node
mathnode = ba.newnode('math',
owner=spaz.node,
attrs={
'input1': (0, 1.4, 0),
'operation': 'add'
})
spaz.node.connectattr('torso_position', mathnode, 'input2')
players_star = ba.newnode('text',
owner=spaz.node,
attrs={
'text': '*',
'in_world': True,
'color': (1, 1, 0.4),
'scale': 0.02,
'h_align': 'center'
})
player.tag = players_star
mathnode.connectattr('output', players_star, 'position')
return spaz
def _update_stars(self, player: Player) -> None:
oldstar = player.tag.text.count("*")
if player.is_alive():
if oldstar < 3:
player.tag.text = "*" * (oldstar + 1)
elif oldstar == 3:
player.tag.text = "**\n**"
elif oldstar == 4:
player.tag.text = "**\n***"
else:
player.tag.text = player.tag.text
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
# Augment standard behavior.
super().handlemessage(msg)
player = msg.getplayer(Player)
self.respawn_player(player)
killer = msg.getkillerplayer(Player)
if killer is None:
return None
try:
star = player.tag.text.count("*")
except:
star = 0
# Handle team-kills.
if killer.team is player.team:
# In free-for-all, killing yourself loses you a point.
if isinstance(self.session, ba.FreeForAllSession):
new_score = player.team.score - 1
if not self._allow_negative_scores:
new_score = max(0, new_score)
player.team.score = new_score
# In teams-mode it gives a point to the other team.
else:
ba.playsound(self._dingsound)
for team in self.teams:
if team is not killer.team:
team.score += star
if not killer == player:
self._update_stars(killer)
# Killing someone on another team nets a kill.
else:
killer.team.score += star
self._update_stars(killer)
ba.playsound(self._dingsound)
# In FFA show scores since its hard to find on the scoreboard.
if isinstance(killer.actor, PlayerSpaz) and killer.actor:
killer.actor.set_score_text("+ 1",
color=killer.team.color,
flash=True)
self._update_scoreboard()
# If someone has won, set a timer to end shortly.
# (allows the dust to clear and draws to occur if deaths are
# close enough)
else:
return super().handlemessage(msg)
return None
def _update_scoreboard(self) -> None:
for team in self.teams:
self._scoreboard.set_team_value(team, team.score,
None)
def end_game(self) -> None:
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)

237
dist/ba_root/mods/games/DarkFields.py vendored Normal file
View file

@ -0,0 +1,237 @@
#Made by Froshlee14
#Ported by: Freaku / @[Just] Freak#4999
# ba_meta require api 6
from __future__ import annotations
from typing import TYPE_CHECKING
import ba,random
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
from bastd.actor.bomb import Bomb
from bastd.gameutils import SharedObjects
if TYPE_CHECKING:
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
class Player(ba.Player['Team']):
"""Our player type for this game."""
class Team(ba.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.score = 0
# ba_meta export game
class DFGame(ba.TeamGameActivity[Player, Team]):
"""A game type based on acquiring kills."""
name = 'Dark Fields'
description = 'Get to the other side.'
# Print messages when players die since it matters here.
announce_player_deaths = True
@classmethod
def get_available_settings(
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
settings = [
ba.IntSetting(
'Score to Win',
min_value=1,
default=3,
increment=1,
),
ba.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
('1 Minute', 60),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600),
('20 Minutes', 1200),
],
default=0,
),
ba.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
('Short', 0.5),
('Normal', 1.0),
('Long', 2.0),
('Longer', 4.0),
],
default=1.0,
),
ba.BoolSetting('Epic Mode', default=False)
]
return settings
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return (issubclass(sessiontype, ba.DualTeamSession)
or issubclass(sessiontype, ba.FreeForAllSession))
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ['Football Stadium']
def __init__(self, settings: dict):
super().__init__(settings)
shared = SharedObjects.get()
self._scoreboard = Scoreboard()
self._dingsound = ba.getsound('dingSmall')
self._epic_mode = bool(settings['Epic Mode'])
self._score_to_win = int(
settings['Score to Win'])
self._time_limit = float(settings['Time Limit'])
# Base class overrides.
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC if self._epic_mode else ba.MusicType.TO_THE_DEATH)
self._scoreRegionMaterial = ba.Material()
self._scoreRegionMaterial.add_actions(
conditions=("they_have_material",shared.player_material),
actions=(("modify_part_collision","collide",True),
("modify_part_collision","physical",False),
("call","at_connect", self._onPlayerScores)))
self.first_time = True
def get_instance_description(self) -> Union[str, Sequence]:
return 'Get to the other side ${ARG1} times', self._score_to_win
def get_instance_description_short(self) -> Union[str, Sequence]:
return 'Get to the other side ${ARG1} times', self._score_to_win
def on_team_join(self, team: Team) -> None:
if self.has_begun():
self._update_scoreboard()
def on_begin(self) -> None:
super().on_begin()
ba.getactivity().globalsnode.tint = (0.5, 0.5, 0.5)
a = ba.newnode('locator',attrs={'shape':'box','position':(12,0,.1087926362),'color':(5,5,5),'opacity':1,'draw_beauty':True,'additive':False,'size':[2.0,0.1,11.8]})
b = ba.newnode('locator',attrs={'shape':'box','position':(-12,0,.1087926362),'color':(5,5,5),'opacity':1,'draw_beauty':True,'additive':False,'size':[2.0,0.1,11.8]})
self.isUpdatingMines = False
self._scoreSound = ba.getsound('dingSmall')
self.setup_standard_time_limit(self._time_limit)
self._update_scoreboard()
for p in self.players:
if p.actor is not None:
try:p.actor.disconnect_controls_from_player()
except Exception as e: print ('Can\'t connect to player',e)
self._scoreRegions = []
defs = self.map.defs
self._scoreRegions.append(ba.NodeActor(ba.newnode('region',
attrs={'position':defs.boxes['goal1'][0:3],
'scale':defs.boxes['goal1'][6:9],
'type': 'box',
'materials':[self._scoreRegionMaterial]})))
self.mines = []
self.spawnMines()
ba.timer(2.5,self.start)
def start(self):
ba.timer(random.randrange(3,7),self.doRandomLighting)
ba.animate_array(ba.getactivity().globalsnode,'tint',3,{0:(0.5,0.5,0.5),2:(0.2,0.2,0.2)})
def doRandomLighting(self):
ba.timer(random.randrange(3,7),self.doRandomLighting)
if self.isUpdatingMines: return
ba.animate_array(ba.getactivity().globalsnode,'tint',3,{0:(0.5,0.5,0.5),0.8:(0.2,0.2,0.2)})
def spawnMines(self):
delay = 0
xs = [10,8,6,4,2,0,-2,-4,-6,-8,-10]
for x in xs:
for i in range(3):
pos = (x,1,random.randrange(-5,6))
ba.timer(delay,ba.Call(self.doMine,pos))
delay += 0.075
ba.timer(2.48,self.stopUpdateMines)
def stopUpdateMines(self):
self.isUpdatingMines = False
self.first_time = False
def updateMines(self):
if self.isUpdatingMines: return
self.isUpdatingMines = True
for m in self.mines:
m.node.delete()
self.mines = []
self.spawnMines()
def doMine(self,pos):
b = Bomb(position=pos,bomb_type='land_mine').autoretain()
b.arm()
self.mines.append(b)
# overriding the default character spawning..
def spawn_player(self, player: Player):
if self.first_time: ba.timer(2.5, ba.Call(self.spawn_with_delay, player))
else: self.spawn_with_delay(player)
def spawn_with_delay(self, player: Player):
spaz = self.spawn_player_spaz(player)
position = (-12.4,1,random.randrange(-5,5))
spaz.connect_controls_to_player(enable_punch=False,enable_bomb=False)
spaz.handlemessage(ba.StandMessage(position, random.uniform(0,360)))
return spaz
def _onPlayerScores(self):
try: player = ba.getcollision().opposingnode.getdelegate(PlayerSpaz, True).getplayer(Player, True)
except Exception: player = None
if player.exists() and player.is_alive():
for team in self.teams:
if team is player.team:
team.score += 1
ba.playsound(self._scoreSound)
ba.animate_array(ba.getactivity().globalsnode,'tint',3,{0:(0.5,0.5,0.5),2.8:(0.2,0.2,0.2)})
self._update_scoreboard()
player.actor.handlemessage(ba.DieMessage())
self.updateMines()
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
# Augment standard behavior.
super().handlemessage(msg)
player = msg.getplayer(Player)
self.respawn_player(player)
self._update_scoreboard()
# If someone has won, set a timer to end shortly.
# (allows the dust to clear and draws to occur if deaths are
# close enough)
assert self._score_to_win is not None
if any(team.score >= self._score_to_win for team in self.teams):
ba.timer(0.5, self.end_game)
else:
return super().handlemessage(msg)
return None
def _update_scoreboard(self) -> None:
for team in self.teams:
self._scoreboard.set_team_value(team, team.score,
self._score_to_win)
def end_game(self) -> None:
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)

487
dist/ba_root/mods/games/EggGame.py vendored Normal file
View file

@ -0,0 +1,487 @@
# Released under the MIT License. See LICENSE for details.
"""Egg game and support classes."""
# The Egg Game - throw egg as far as you can
# created in BCS (Bombsquad Consultancy Service) - opensource bombsquad mods for all
# discord.gg/ucyaesh join now and give your contribution
# The Egg game by mr.smoothy
# ba_meta require api 6
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
from bastd.actor.powerupbox import PowerupBoxFactory
from bastd.gameutils import SharedObjects
from bastd.actor.flag import Flag
import math
import random
if TYPE_CHECKING:
from typing import Any, Sequence, Dict, Type, List, Optional, Union
class PuckDiedMessage:
"""Inform something that a puck has died."""
def __init__(self, puck: Puck):
self.puck = puck
class Puck(ba.Actor):
"""A lovely giant hockey puck."""
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)):
super().__init__()
shared = SharedObjects.get()
activity = self.getactivity()
# Spawn just above the provided point.
self._spawn_pos = (position[0], position[1] + 1.0, position[2])
self.last_players_to_touch =None
self.scored = False
self.egg_model = ba.getmodel('egg')
self.egg_tex_1 = ba.gettexture('eggTex1')
self.egg_tex_2 = ba.gettexture('eggTex2')
self.egg_tex_3 = ba.gettexture('eggTex3')
self.eggtx=[self.egg_tex_1,self.egg_tex_2,self.egg_tex_3]
regg=random.randrange(0,3)
assert activity is not None
assert isinstance(activity, EggGame)
pmats = [shared.object_material, activity.puck_material]
self.node = ba.newnode('prop',
delegate=self,
attrs={
'model': self.egg_model,
'color_texture': self.eggtx[regg],
'body': 'capsule',
'reflection': 'soft',
'reflection_scale': [0.2],
'shadow_size': 0.5,
'body_scale':0.7,
'is_area_of_interest': True,
'position': self._spawn_pos,
'materials': pmats
})
ba.animate(self.node, 'model_scale', {0: 0, 0.2: 0.7, 0.26: 0.6})
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
assert self.node
self.node.delete()
activity = self._activity()
if activity and not msg.immediate:
activity.handlemessage(PuckDiedMessage(self))
# If we go out of bounds, move back to where we started.
elif isinstance(msg, ba.OutOfBoundsMessage):
assert self.node
self.node.position = self._spawn_pos
elif isinstance(msg, ba.HitMessage):
assert self.node
assert msg.force_direction is not None
self.node.handlemessage(
'impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0],
msg.velocity[1], msg.velocity[2], 1.0 * msg.magnitude,
1.0 * msg.velocity_magnitude, msg.radius, 0,
msg.force_direction[0], msg.force_direction[1],
msg.force_direction[2])
# If this hit came from a player, log them as the last to touch us.
s_player = msg.get_source_player(Player)
if s_player is not None:
activity = self._activity()
if activity:
if s_player in activity.players:
self.last_players_to_touch = s_player
else:
super().handlemessage(msg)
class Player(ba.Player['Team']):
"""Our player type for this game."""
class Team(ba.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.score = 0
# ba_meta export game
class EggGame(ba.TeamGameActivity[Player, Team]):
"""Egg game."""
name = 'Epic Egg Game'
description = 'Score some goals.'
available_settings = [
ba.IntSetting(
'Score to Win',
min_value=1,
default=1,
increment=1,
),
ba.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
('40 Seconds', 40),
('1 Minute', 60),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600),
('20 Minutes', 1200),
],
default=0,
),
ba.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.1),
('Short', 0.5),
('Normal', 1.0),
('Long', 2.0),
('Longer', 4.0),
],
default=1.0,
),
]
default_music = ba.MusicType.HOCKEY
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.DualTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ba.getmaps('football')
def __init__(self, settings: dict):
super().__init__(settings)
shared = SharedObjects.get()
self.slow_motion = True
self._scoreboard = Scoreboard()
self._cheer_sound = ba.getsound('cheer')
self._chant_sound = ba.getsound('crowdChant')
self._foghorn_sound = ba.getsound('foghorn')
self._swipsound = ba.getsound('swip')
self._whistle_sound = ba.getsound('refWhistle')
self.puck_model = ba.getmodel('bomb')
self.puck_tex = ba.gettexture('landMine')
self.puck_scored_tex = ba.gettexture('landMineLit')
self._puck_sound = ba.getsound('metalHit')
self.puck_material = ba.Material()
self._fake_wall_material=ba.Material()
self.HIGHEST=0
self._fake_wall_material.add_actions(
conditions=('they_have_material', shared.player_material),
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)
))
self.puck_material.add_actions(actions=(('modify_part_collision',
'friction', 0.5)))
self.puck_material.add_actions(conditions=('they_have_material',
shared.pickup_material),
actions=('modify_part_collision',
'collide', True))
self.puck_material.add_actions(
conditions=(
('we_are_younger_than', 100),
'and',
('they_have_material', shared.object_material),
),
actions=('modify_node_collision', 'collide', False),
)
# self.puck_material.add_actions(conditions=('they_have_material',
# shared.footing_material),
# actions=('impact_sound',
# self._puck_sound, 0.2, 5))
# Keep track of which player last touched the puck
self.puck_material.add_actions(
conditions=('they_have_material', shared.player_material),
actions=(('call', 'at_connect',
self._handle_puck_player_collide), ))
# We want the puck to kill powerups; not get stopped by them
self.puck_material.add_actions(
conditions=('they_have_material',
PowerupBoxFactory.get().powerup_material),
actions=(('modify_part_collision', 'physical', False),
('message', 'their_node', 'at_connect', ba.DieMessage())))
# self.puck_material.add_actions(
# conditions=('they_have_material',shared.footing_material)
# actions=(('modify_part_collision', 'collide',
# True), ('modify_part_collision', 'physical', True),
# ('call', 'at_connect', self._handle_egg_collision))
# )
self._score_region_material = ba.Material()
self._score_region_material.add_actions(
conditions=('they_have_material', self.puck_material),
actions=(('modify_part_collision', 'collide',
True), ('modify_part_collision', 'physical', False),
('call', 'at_connect', self._handle_score)))
self.main_ground_material= ba.Material()
self.main_ground_material.add_actions(
conditions=('they_have_material', self.puck_material),
actions=(('modify_part_collision', 'collide',
True), ('modify_part_collision', 'physical', False),
('call', 'at_connect', self._handle_egg_collision)))
self._puck_spawn_pos: Optional[Sequence[float]] = None
self._score_regions: Optional[List[ba.NodeActor]] = None
self._puck: Optional[Puck] = None
self._pucks=[]
self._score_to_win = int(settings['Score to Win'])
self._time_limit = float(settings['Time Limit'])
def get_instance_description(self) -> Union[str, Sequence]:
return "Throw Egg as far u can"
def get_instance_description_short(self) -> Union[str, Sequence]:
return "Throw Egg as far u can"
def on_begin(self) -> None:
super().on_begin()
if self._time_limit==0.0:
self._time_limit=60
self.setup_standard_time_limit(self._time_limit)
# self.setup_standard_powerup_drops()
self._puck_spawn_pos = self.map.get_flag_position(None)
self._spawn_puck()
self._spawn_puck()
self._spawn_puck()
self._spawn_puck()
self._spawn_puck()
# Set up the two score regions.
defs = self.map.defs
self._score_regions = []
pos=(11.88630542755127, 0.3009839951992035, 1.33331298828125)
# mat=ba.Material()
# mat.add_actions(
# actions=( ('modify_part_collision','physical',True),
# ('modify_part_collision','collide',True))
# )
# self._score_regions.append(
# ba.NodeActor(
# ba.newnode('region',
# attrs={
# 'position': pos,
# 'scale': (2,3,5),
# 'type': 'box',
# 'materials': [self._score_region_material]
# })))
# pos=(-11.88630542755127, 0.3009839951992035, 1.33331298828125)
# self._score_regions.append(
# ba.NodeActor(
# ba.newnode('region',
# attrs={
# 'position': pos,
# 'scale': (2,3,5),
# 'type': 'box',
# 'materials': [self._score_region_material]
# })))
self._score_regions.append(
ba.NodeActor(
ba.newnode('region',
attrs={
'position': (-9.21,defs.boxes['goal2'][0:3][1],defs.boxes['goal2'][0:3][2]),
'scale': defs.boxes['goal2'][6:9],
'type': 'box',
'materials': (self._fake_wall_material, )
})))
pos=(0,0.1,-5)
self.main_ground=ba.newnode('region',attrs={'position': pos,'scale': (25,0.001,22),'type': 'box','materials': [self.main_ground_material]})
self._update_scoreboard()
ba.playsound(self._chant_sound)
def on_team_join(self, team: Team) -> None:
self._update_scoreboard()
def _handle_puck_player_collide(self) -> None:
collision = ba.getcollision()
try:
puck = collision.sourcenode.getdelegate(Puck, True)
player = collision.opposingnode.getdelegate(PlayerSpaz,
True).getplayer(
Player, True)
except ba.NotFoundError:
return
puck.last_players_to_touch = player
def _kill_puck(self) -> None:
self._puck = None
def _handle_egg_collision(self) -> None:
no=ba.getcollision().opposingnode
pos=no.position
egg=no.getdelegate(Puck)
source_player=egg.last_players_to_touch
if source_player==None or pos[0]< -8 or not source_player.node.exists() :
return
try:
col=source_player.team.color
self.flagg=Flag(pos,touchable=False,color=col).autoretain()
self.flagg.is_area_of_interest=True
player_pos=source_player.node.position
distance = math.sqrt( pow(player_pos[0]-pos[0],2) + pow(player_pos[2]-pos[2],2))
dis_mark=ba.newnode('text',
attrs={
'text':str(round(distance,2))+"m",
'in_world':True,
'scale':0.02,
'h_align':'center',
'position':(pos[0],1.6,pos[2]),
'color':col
})
ba.animate(dis_mark,'scale',{
0.0:0, 0.5:0.01
})
if distance > self.HIGHEST:
self.HIGHEST=distance
self.stats.player_scored(
source_player,
10,
big_message=False)
no.delete()
ba.timer(2,self._spawn_puck)
source_player.team.score=int(distance)
except():
pass
def spawn_player(self, player: Player) -> ba.Actor:
zoo=random.randrange(-4,5)
pos=(-11.204887390136719, 0.2998693287372589, zoo)
spaz = self.spawn_player_spaz(
player, position=pos, angle=90 )
assert spaz.node
# Prevent controlling of characters before the start of the race.
return spaz
def _handle_score(self) -> None:
"""A point has been scored."""
assert self._puck is not None
assert self._score_regions is not None
# Our puck might stick around for a second or two
# we don't want it to be able to score again.
if self._puck.scored:
return
region = ba.getcollision().sourcenode
index = 0
for index in range(len(self._score_regions)):
if region == self._score_regions[index].node:
break
for team in self.teams:
if team.id == index:
scoring_team = team
team.score += 1
# Tell all players to celebrate.
for player in team.players:
if player.actor:
player.actor.handlemessage(ba.CelebrateMessage(2.0))
# If we've got the player from the scoring team that last
# touched us, give them points.
if (scoring_team.id in self._puck.last_players_to_touch
and self._puck.last_players_to_touch[scoring_team.id]):
self.stats.player_scored(
self._puck.last_players_to_touch[scoring_team.id],
20,
big_message=True)
# End game if we won.
if team.score >= self._score_to_win:
self.end_game()
ba.playsound(self._foghorn_sound)
ba.playsound(self._cheer_sound)
# self._puck.scored = True
# Change puck texture to something cool
# self._puck.node.color_texture = self.puck_scored_tex
# Kill the puck (it'll respawn itself shortly).
ba.timer(1.0, self._kill_puck)
# light = ba.newnode('light',
# attrs={
# 'position': ba.getcollision().position,
# 'height_attenuated': False,
# 'color': (1, 0, 0)
# })
# ba.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
# ba.timer(1.0, light.delete)
ba.cameraflash(duration=10.0)
self._update_scoreboard()
def end_game(self) -> None:
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)
def _update_scoreboard(self) -> None:
winscore = self._score_to_win
# for team in self.teams:
# self._scoreboard.set_team_value(team, team.score, winscore)
def handlemessage(self, msg: Any) -> Any:
# Respawn dead players if they're still in the game.
if isinstance(msg, ba.PlayerDiedMessage):
# Augment standard behavior...
super().handlemessage(msg)
self.respawn_player(msg.getplayer(Player))
# Respawn dead pucks.
elif isinstance(msg, PuckDiedMessage):
if not self.has_ended():
ba.timer(3.0, self._spawn_puck)
else:
super().handlemessage(msg)
def _flash_puck_spawn(self) -> None:
# light = ba.newnode('light',
# attrs={
# 'position': self._puck_spawn_pos,
# 'height_attenuated': False,
# 'color': (1, 0, 0)
# })
# ba.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True)
# ba.timer(1.0, light.delete)
pass
def _spawn_puck(self) -> None:
# ba.playsound(self._swipsound)
# ba.playsound(self._whistle_sound)
self._flash_puck_spawn()
assert self._puck_spawn_pos is not None
zoo=random.randrange(-5,6)
pos=(-11.204887390136719, 0.2998693287372589, zoo)
self._pucks.append (Puck(position=pos))

293
dist/ba_root/mods/games/GetTheTarget.py vendored Normal file
View file

@ -0,0 +1,293 @@
# Made by Froshlee14
# ba_meta require api 6
from __future__ import annotations
from typing import TYPE_CHECKING
import ba, _ba, random
from bastd.actor.scoreboard import Scoreboard
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor import spaz
if TYPE_CHECKING:
from typing import Any, Union, Type, List, Dict, Tuple, Sequence, Optional
class Player(ba.Player['Team']):
"""Our player type for this game."""
class Team(ba.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.score = 0
# ba_meta export game
class GetTheTargetGame(ba.TeamGameActivity[Player, Team]):
name = 'Get the Target'
description = 'Kill target to get points (dont kill if teammate). If you\'re \nthe Target, survive to get points, \nplayer/team that reached the\n required points, wins.'
announce_player_deaths = True
@classmethod
def get_available_settings(
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
settings = [
ba.IntSetting("Points to Win Per Player", min_value=1, default=5, increment=1),
ba.IntSetting("Time to Kill", min_value=5, max_value=30, default=10, increment=1),
ba.IntChoiceSetting("Time Limit", choices=[('None', 0),('1 Minute', 60),('2 Minutes', 120),('5 Minutes', 300),('10 Minutes', 600),('20 Minutes', 1200)],default=0),
ba.FloatChoiceSetting("Respawn Times",choices=[('Shorter', 0.25),('Short', 0.5),('Normal', 1.0),('Long', 2.0),('Longer', 4.0)],default=1.0),
ba.IntChoiceSetting("Target Indicator", choices=[('None', 0),('Light', 1),('Text', 2)],default=0),
ba.BoolSetting("Epic Mode", default=False)
]
return settings
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return (issubclass(sessiontype, ba.DualTeamSession)
or issubclass(sessiontype, ba.FreeForAllSession))
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ba.getmaps('melee')
def __init__(self, settings: dict):
super().__init__(settings)
self.settings = settings
if self.settings['Epic Mode']: self.slow_motion = True
self._chosed_player = self.chosen_player = None
self._score_to_win: Optional[int] = None
self._dingsound = ba.getsound('dingSmall')
self._chosing_sound = ba.getsound('scoreIncrease')
self._chosed_sound = ba.getsound('cashRegister2')
self._error_sound = ba.getsound('error')
self._tick_sound = ba.getsound('tick')
self._time_remaining = int(self.settings['Time to Kill'])
self._time_limit = float(settings['Time Limit'])
self.ytpe = int(settings["Target Indicator"])
self._scoreboard = Scoreboard()
self.default_music = (ba.MusicType.EPIC if self.slow_motion else
ba.MusicType.TO_THE_DEATH)
def get_instance_description(self) -> Union[str, Sequence]:
return 'Kill enemy targets or Survive ${ARG1} times.', self._score_to_win
def get_instance_scoreboard_display_string(self) -> str:
return 'Kill target/Survive ' + str(self._score_to_win) + ' times.'
def on_team_join(self, team: Team) -> None:
if self.has_begun(): self._update_scoreboard()
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self._time_limit)
self.setup_standard_powerup_drops()
self._score_to_win = (int(self.settings["Points to Win Per Player"]) *
max(1, max(len(t.players) for t in self.teams)))
self._update_scoreboard()
ba.timer(3000 * 0.001, self.star_chosing_player)
self._chose_text = ba.newnode('text',
attrs={
'text':' ',
'v_attach':'bottom',
'h_attach':'center',
'h_align':'center',
'v_align':'center',
'maxwidth':150,
'shadow':1.0,
'flatness':1.0,
'color':(1,1,1),
'scale':1,
'position':(0,155)})
def on_player_leave(self, player: PlayerType) -> None:
super().on_player_leave(player)
if len(self.players) in [0,1]: self.end_game()
if player == self._chosed_player: self.star_chosing_player()
def print_random_icon(self) -> None:
get_alive = []
for spas in self.players:
if spas.is_alive():
get_alive.append(spas)
if not len(get_alive) == 0:
self._chose_text.text = 'Chosing Player...'
self.loops += 1
player = random.choice(get_alive)
icon = player.get_icon()
outline_tex = ba.gettexture('characterIconMask')
texture = icon['texture']
self._image = ba.NodeActor(ba.newnode('image',
attrs={'texture':texture,
'tint_texture':icon['tint_texture'],
'tint_color':icon['tint_color'],
'tint2_color':icon['tint2_color'],
'mask_texture':outline_tex,
'position':(0,80),
'scale':(100,100), 'opacity':1.0,
'absolute_scale':True,'attach':'bottomCenter'}))
self._name = ba.NodeActor(ba.newnode('text',
attrs={'v_attach':'bottom', 'h_attach':'center',
'text':ba.Lstr(value=player.getname()),
'maxwidth':100, 'h_align':'center',
'v_align':'center', 'shadow':1.0,
'flatness':1.0, 'color':ba.safecolor(icon['tint_color']),
'scale':1,'position':(0,20)}))
if self.loops >= self.loop_max:
self.chosen_player = player
self.stopn_chose_player()
else:
self._chose_text.text = 'Waiting for players...'
texture = ba.gettexture("powerupCurse")
self._image = ba.NodeActor(ba.newnode('image',
attrs={'texture':texture,
'position':(0,80),
'scale':(100,100), 'opacity':1.0,
'absolute_scale':True,'attach':'bottomCenter'}))
self._name = ba.NodeActor(ba.newnode('text',
attrs={'v_attach':'bottom', 'h_attach':'center',
'text':" ",
'maxwidth':100, 'h_align':'center',
'v_align':'center', 'shadow':1.0,
'flatness':1.0,
'color':(1,1,1),
'scale':1,'position':(0,20)}))
return
def star_chosing_player(self) -> None:
if len(self.players) in [0,1]: self.end_game()
self._sound = ba.NodeActor(ba.newnode('sound',attrs={'sound':self._chosing_sound,'volume':1.0}))
self.stop_timer()
self.loops = 0
self.loop_max = random.randrange(15,30)
self._chosed_player = None
self._logo_effect = ba.Timer(80 * 0.001,ba.WeakCall(self.print_random_icon),repeat=True)
self._chose_text.color = (1,1,1)
def stopn_chose_player(self) -> None:
self._sound = None
self._logo_effect = None
ba.playsound(self._chosed_sound)
player = self.chosen_player
self._chosed_player = player
self._chose_text.text = 'Kill the Enemy!'
self._chose_text.color = (1,1,0)
palyer = player.actor
if self.ytpe == 1:
palyer.r = ba.newnode('light',
attrs={
'radius':0.2,
'intensity': 5.0,
'color': palyer.node.color
})
palyer.node.connectattr('position', palyer.r, 'position')
elif self.ytpe == 2:
dummy = ba.newnode('math',owner=palyer.node,attrs={'input1': (0, 1.25, 0),'operation': 'add'})
palyer.node.connectattr('position', dummy, 'input2')
palyer.r = ba.newnode('text',owner=palyer.node,
attrs={'text': 'TARGET!',
'in_world': True,
'shadow': 1.0,
'flatness': 1.5,
'scale': 0.014,
'h_align': 'center',})
ba.animate_array(palyer.r,'color',3,{
0.0:(0.3, 0.3, 1.0),
0.5:(1, 0.3, 0.3),
1.0:(0.3, 1 , 0.3),
2.0:(0.3, 0.3, 1.0)
}, True)
dummy.connectattr('output', palyer.r, 'position')
self.start_timer()
def start_timer(self) -> None:
self._time_remaining = self.settings['Time to Kill']
self._timer_x = ba.Timer(1000*0.001,ba.WeakCall(self.tick),repeat=True)
def stop_timer(self) -> None:
self._time = None
self._timer_x = None
def tick(self) -> None:
self.check_for_expire()
self._time = ba.NodeActor(ba.newnode('text',
attrs={'v_attach':'top', 'h_attach':'center',
'text':('Kill Time: '+str(self._time_remaining)+'s'), 'opacity': 0.8,
'maxwidth':100, 'h_align':'center',
'v_align':'center', 'shadow':1.0,
'flatness':1.0, 'color':(1,1,1),
'scale':2,'position':(0,-100)}))
self._time_remaining -= 1
ba.playsound(self._tick_sound)
def check_for_expire(self) -> None:
if self._time_remaining <= 0:
self.stop_timer()
if len(self.players) == 0: pass
elif self._chosed_player.is_alive():
player = self._chosed_player
player.team.score += 1
player.actor.r.delete()
ba.playsound(self._dingsound)
self._update_scoreboard()
if any(team.score >= self._score_to_win for team in self.teams):
ba.timer(500*0.001,self.end_game)
self._chose_text.text = 'Survived!'
self._chose_text.color = (0,1,0)
ba.timer(600*0.001,self.star_chosing_player)
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
super().handlemessage(msg)
player = msg.getplayer(Player)
self.respawn_player(player)
killer = msg.getkillerplayer(Player)
assert self._score_to_win is not None
if player == self._chosed_player:
self._chosed_player.actor.r.delete()
if killer.team is player.team:
if isinstance(self.session, ba.FreeForAllSession):
player.team.score = max(0,player.team.score-1)
else:
ba.playsound(self._dingsound)
for team in self.teams:
if team is not killer.team:
team.score += 1
else:
killer.team.score += 1
ba.playsound(self._dingsound)
try: killer.actor.set_score_text(str(killer.team.score)+'/'+str(self._score_to_win),color=killer.team.color,flash=True)
except Exception: pass
self._update_scoreboard()
if any(team.score >= self._score_to_win for team in self.teams):
ba.timer(500*0.001,self.end_game)
if killer != self._chosed_player:
self._chose_text.text = 'Killed!'
self._chose_text.color = (1,0.5,0)
else:
self._chose_text.text = 'Dead!'
self._chose_text.color = (1.0,0,0)
ba.playsound(self._error_sound)
ba.timer(600*0.001,self.star_chosing_player)
else: super().handlemessage(msg)
def _update_scoreboard(self) -> None:
for team in self.teams:
self._scoreboard.set_team_value(team, team.score,
self._score_to_win)
def end_game(self) -> None:
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)

31
dist/ba_root/mods/games/GravityFalls.py vendored Normal file
View file

@ -0,0 +1,31 @@
## Made by MattZ45986 on GitHub
## Ported by: Freaku / @[Just] Freak#4999
import ba
from bastd.game.elimination import EliminationGame
# ba_meta require api 6
# ba_meta export game
class GFGame(EliminationGame):
name = 'Gravity Falls'
def spawn_player(self, player):
actor = self.spawn_player_spaz(player, (0,5,0))
if not self._solo_mode:
ba.timer(0.3, ba.Call(self._print_lives, player))
# If we have any icons, update their state.
for icon in player.icons:
icon.handle_player_spawned()
ba.timer(1,ba.Call(self.raise_player, player))
return actor
def raise_player(self, player):
if player.is_alive():
try:
player.actor.node.handlemessage("impulse",player.actor.node.position[0],player.actor.node.position[1]+.5,player.actor.node.position[2],0,5,0, 3,10,0,0, 0,5,0)
except: pass
ba.timer(0.05,ba.Call(self.raise_player,player))

676
dist/ba_root/mods/games/Heist.py vendored Normal file
View file

@ -0,0 +1,676 @@
# ba_meta require api 6
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
import _ba
import math
import random
from bastd.actor import spawner
from bastd.actor.bomb import BombFactory
from bastd.actor.spazfactory import SpazFactory
from bastd.gameutils import SharedObjects
from bastd.actor.bomb import ExplodeHitMessage
from ba._gameutils import show_damage_count
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.powerupbox import PowerupBox
from bastd.actor.spazbot import SpazBotSet, ExplodeyBotNoTimeLimit
if TYPE_CHECKING:
from typing import Any, Union, Sequence, Optional
class Blast(ba.Actor):
def __init__(self,
position: Sequence[float] = (0.0, 1.0, 0.0),
blast_radius: float = 2.0,
color: Sequence[float] = (0.0, 1.0, 0.0)):
super().__init__()
shared = SharedObjects.get()
factory = BombFactory.get()
self.radius = blast_radius
rmats = (factory.blast_material, shared.attack_material)
self.node = ba.newnode(
'region',
delegate=self,
attrs={
'position': (position[0], position[1] - 0.1, position[2]),
'scale': (self.radius, self.radius, self.radius),
'type': 'sphere',
'materials': rmats
},
)
ba.timer(0.05, self.node.delete)
explosion = ba.newnode('explosion',
attrs={
'position': position,
'radius': self.radius * 0.8,
'color': (color[0] * 0.3,
color[1] * 0.3,
color[2] * 0.3),
'big': True
})
ba.timer(1.0, explosion.delete)
light = ba.newnode('light',
attrs={
'position': position,
'volume_intensity_scale': 10.0,
'color': (1, 0.3, 0.1)
})
scl = random.uniform(0.6, 0.9) * 3.0
scorch_radius = self.radius * 1.4
light_radius = self.radius * 0.6
iscale = 0.8
ba.animate(
light, 'intensity', {
0: 2.0 * iscale,
scl * 0.02: 0.1 * iscale,
scl * 0.025: 0.2 * iscale,
scl * 0.05: 17.0 * iscale,
scl * 0.06: 5.0 * iscale,
scl * 0.08: 4.0 * iscale,
scl * 0.2: 0.6 * iscale,
scl * 2.0: 0.00 * iscale,
scl * 3.0: 0.0
})
ba.animate(
light, 'radius', {
0: light_radius * 0.2,
scl * 0.05: light_radius * 0.55,
scl * 0.1: light_radius * 0.3,
scl * 0.3: light_radius * 0.15,
scl * 1.0: light_radius * 0.05
})
ba.timer(scl * 3.0, light.delete)
scorch = ba.newnode('scorch',
attrs={
'position': position,
'size': scorch_radius * 0.5,
'color': (color[0] * 0.6,
color[1] * 0.6,
color[2] * 0.6),
'big': True
})
ba.animate(scorch, 'presence', {3.000: 1, 13.000: 0})
ba.timer(13.0, scorch.delete)
lpos = light.position
ba.playsound(factory.random_explode_sound(), position=lpos)
ba.playsound(factory.random_explode_sound(), position=lpos)
ba.playsound(factory.debris_fall_sound, position=lpos)
ba.camerashake(intensity=5.0)
def _extra_boom() -> None:
ba.playsound(factory.random_explode_sound(), position=lpos)
ba.timer(0.25, _extra_boom)
def _extra_debris_sound() -> None:
ba.playsound(factory.debris_fall_sound, position=lpos)
ba.playsound(factory.wood_debris_fall_sound, position=lpos)
ba.timer(0.4, _extra_debris_sound)
# ba.emitfx(position=position,
# count=100,
# scale=1.8,
# spread=5,
# chunk_type='spark')
# ba.emitfx(position=position,
# count=100,
# spread=5,
# scale=2,
# chunk_type='ice',
# emit_type='stickers')
ba.emitfx(position=position,
count=1000,
spread=500,
scale=10,
chunk_type='slime')
# ba.emitfx(position=position,
# count=20,
# scale=1,
# spread=500,
# chunk_type='sweat',
# emit_type='tendrils')
def handlemessage(self, msg: Any) -> Any:
assert not self.expired
if isinstance(msg, ba.DieMessage):
if self.node:
self.node.delete()
elif isinstance(msg, ExplodeHitMessage):
node = ba.getcollision().opposingnode
assert self.node
nodepos = self.node.position
mag = 2000.0
mag *= 2.0
node.handlemessage(
ba.HitMessage(pos=nodepos,
velocity=(0, 0, 0),
magnitude=mag,
hit_type='explosion',
hit_subtype='normal',
radius=self.radius))
else:
return super().handlemessage(msg)
return None
class TNTBox(ba.Actor):
def __init__(self,
team_id: ba.Team,
modeltype: float = None,
position: Sequence[float] = None,
hitpoints: float = 1000,
team: str = None):
super().__init__()
shared = SharedObjects.get()
activity = self.getactivity()
spaz = SpazFactory.get()
self.team = team_id
self.modeltype = modeltype
self.team_str = team
self.teamcolor = team_id.color
self.position = position
self.hitpoints = hitpoints
self.hitpoints_max = hitpoints
self._width = 240
self._width_max = 240
self._height = 35
self._bar_width = 240
self._bar_height = 35
self._bar_tex = self._backing_tex = ba.gettexture('bar')
self._cover_tex = ba.gettexture('uiAtlas')
self._model = ba.getmodel('meterTransparent')
if team == 'team 1':
self.bar_posx = -200 - 120
else:
self.bar_posx = 200 - 120
self.box_material = ba.Material()
no_collide_material = ba.Material()
self.box_material.add_actions(
conditions=('they_have_material', shared.pickup_material),
actions=('modify_part_collision', 'collide', False),
)
if modeltype == 1:
self.node = ba.newnode(
'prop',
delegate=self,
attrs={
'position': (position[0], position[1] + 2.5, position[2]),
'model': ba.getmodel('tnt'),
'light_model': ba.getmodel('tnt'),
'body': 'crate',
'body_scale': 3.3,
'model_scale': 3.35,
'shadow_size': 0.3,
'color_texture': ba.gettexture('tickets'),
'is_area_of_interest': True,
'reflection': 'soft',
'reflection_scale': [0.23],
'materials': [self.box_material, shared.footing_material]
})
elif modeltype == 2:
self.node = ba.newnode(
'prop',
delegate=self,
attrs={
'position': (position[0], position[1] + 1.5, position[2]),
'model': ba.getmodel('tnt'),
'light_model': ba.getmodel('tnt'),
'body': 'crate',
'body_scale': 1,
'model_scale': 1,
'shadow_size': 0.3,
'color_texture': ba.gettexture('tnt'),
'is_area_of_interest': True,
'reflection': 'soft',
'reflection_scale': [0.23],
'materials': [self.box_material, shared.footing_material]
})
elif modeltype == 3:
self.node = ba.newnode(
'prop',
delegate=self,
attrs={
'position': (position[0], position[1] + 1.5, position[2]),
'model': ba.getmodel('puck'),
'body': 'puck',
'body_scale': 1,
'model_scale': 1,
'shadow_size': 1.0,
'color_texture': ba.gettexture('puckColor'),
'is_area_of_interest': True,
'reflection': 'soft',
'reflection_scale': [0.23],
'materials': [self.box_material, shared.footing_material]
})
elif modeltype == 4:
self.node = ba.newnode(
'prop',
delegate=self,
attrs={
'position': (position[0], position[1] + 1.5, position[2]),
'model': ba.getmodel('frostyPelvis'),
'body': 'sphere',
'body_scale': 2.5,
'model_scale': 2.5,
'shadow_size': 0.3,
'color_texture': ba.gettexture('frostyColor'),
'is_area_of_interest': True,
'reflection': 'soft',
'reflection_scale': [1.0],
'materials': [self.box_material, shared.footing_material]
})
ba.animate(self.node, 'model_scale', {
0: 0,
0.2: self.node.model_scale * 1.1,
0.26: self.node.model_scale})
light = ba.newnode(
'light',
owner=self.node,
attrs={
'radius': 0.28,
'color': self.teamcolor
})
self.node.connectattr('position', light, 'position')
self._scoreboard()
self._update()
def animate_model(self) -> None:
if not self.node:
return None
ba.animate(self.node, 'model_scale', {
0: self.node.model_scale,
0.08: self.node.model_scale * 0.9,
0.15: self.node.model_scale})
if self.modeltype in [1,2]:
ba.emitfx(position=self.node.position,
velocity=self.node.velocity,
count=int(6 + random.random() * 10),
scale=0.5,
spread=0.4,
chunk_type='splinter')
elif self.modeltype == 3:
ba.emitfx(position=self.node.position,
velocity=self.node.velocity,
count=int(4 + random.random() * 4),
scale=0.5,
spread=0.3,
chunk_type='metal')
else:
ba.emitfx(position=self.node.position,
velocity=self.node.velocity,
count=int(4 + random.random() * 4),
scale=0.5,
spread=0.3,
chunk_type='ice')
def do_damage(self, msg: Any) -> None:
if not self.node:
return None
damage = msg.magnitude
self.hitpoints -= int(damage)
if self.hitpoints <= 0:
self.hitpoints = 0
Blast(
position=self.node.position,
blast_radius=20.0,
color=self.teamcolor).autoretain()
self.node.delete()
def _update(self) -> None:
self._score_text.node.text = str(self.hitpoints)
self._bar_width = self.hitpoints * self._width_max / self.hitpoints_max
cur_width = self._bar_scale.input0
ba.animate(self._bar_scale, 'input0', {
0.0: cur_width,
0.1: self._bar_width
})
cur_x = self._bar_position.input0
if self.team_str == 'team 1':
ba.animate(self._bar_position, 'input0', {
0.0: cur_x,
0.1: self.bar_posx*0.265 - self._bar_width / 2
})
else:
ba.animate(self._bar_position, 'input0', {
0.0: cur_x,
0.1: self.bar_posx + self._bar_width / 2
})
def show_damage_msg(self, msg: Any) -> None:
if not self.node:
return None
damage = msg.magnitude
self.show_damage_count('-' + str(int(damage)),
self.node.position,
(msg.force_direction[0]*0.2,
msg.force_direction[1]*0.2,
msg.force_direction[2]*0.2,))
def show_damage_count(self, damage: str, position: Sequence[float],
direction: Sequence[float]) -> None:
"""Pop up a damage count at a position in space.
Category: Gameplay Functions
"""
lifespan = 1.0
app = ba.app
# FIXME: Should never vary game elements based on local config.
# (connected clients may have differing configs so they won't
# get the intended results).
do_big = app.ui.uiscale is ba.UIScale.SMALL or app.vr_mode
txtnode = ba.newnode('text',
attrs={
'text': damage,
'in_world': True,
'h_align': 'center',
'flatness': 1.0,
'shadow': 1.0 if do_big else 0.7,
'color': (1, 0.25, 0.25, 1),
'scale': 0.035 if do_big else 0.03
})
# Translate upward.
tcombine = ba.newnode('combine', owner=txtnode, attrs={'size': 3})
tcombine.connectattr('output', txtnode, 'position')
v_vals = []
pval = 0.0
vval = 0.07
count = 6
for i in range(count):
v_vals.append((float(i) / count, pval))
pval += vval
vval *= 0.5
p_start = position[0]
p_dir = direction[0]
ba.animate(tcombine, 'input0',
{i[0] * lifespan: p_start + p_dir * i[1]
for i in v_vals})
p_start = position[1]
p_dir = direction[1]
ba.animate(tcombine, 'input1',
{i[0] * lifespan: p_start + p_dir * i[1]
for i in v_vals})
p_start = position[2]
p_dir = direction[2]
ba.animate(tcombine, 'input2',
{i[0] * lifespan: p_start + p_dir * i[1]
for i in v_vals})
ba.animate(txtnode, 'opacity', {0.7 * lifespan: 1.0, lifespan: 0.0})
ba.timer(lifespan, txtnode.delete)
def _scoreboard(self) -> None:
self._backing = ba.NodeActor(
ba.newnode('image',
attrs={
'position': (self.bar_posx + self._width / 2, -35),
'scale': (self._width, self._height),
'opacity': 0.7,
'color': (self.teamcolor[0] * 0.2,
self.teamcolor[1] * 0.2,
self.teamcolor[2] * 0.2),
'vr_depth': -3,
'attach': 'topCenter',
'texture': self._backing_tex
}))
self._bar = ba.NodeActor(
ba.newnode('image',
attrs={
'opacity': 1.0,
'color': self.teamcolor,
'attach': 'topCenter',
'texture': self._bar_tex
}))
self._bar_scale = ba.newnode('combine',
owner=self._bar.node,
attrs={
'size': 2,
'input0': self._bar_width,
'input1': self._bar_height
})
self._bar_scale.connectattr('output', self._bar.node, 'scale')
self._bar_position = ba.newnode(
'combine',
owner=self._bar.node,
attrs={
'size': 2,
'input0': self.bar_posx + self._bar_width / 2,
'input1': -35
})
self._bar_position.connectattr('output', self._bar.node, 'position')
self._cover = ba.NodeActor(
ba.newnode('image',
attrs={
'position': (self.bar_posx + 120, -35),
'scale':
(self._width * 1.15, self._height * 1.6),
'opacity': 1.0,
'color': (self.teamcolor[0] * 1.1,
self.teamcolor[1] * 1.1,
self.teamcolor[2] * 1.1),
'vr_depth': 2,
'attach': 'topCenter',
'texture': self._cover_tex,
'model_transparent': self._model
}))
self._score_text = ba.NodeActor(
ba.newnode('text',
attrs={
'position': (self.bar_posx + 120, -35),
'h_attach': 'center',
'v_attach': 'top',
'h_align': 'center',
'v_align': 'center',
'maxwidth': 130,
'scale': 0.9,
'text': '',
'shadow': 0.5,
'flatness': 1.0,
'color': (1,1,1,0.8)
}))
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.HitMessage):
self.animate_model()
self.do_damage(msg)
# self.show_damage_msg(msg)
self._update()
elif isinstance(msg, ba.DieMessage):
if self.node:
self.node.delete()
elif isinstance(msg, ba.OutOfBoundsMessage):
if self.node:
self.node.position = self.position
self.node.velocity = (0,0,0)
else:
super().handlemessage(msg)
class Player(ba.Player['Team']):
"""Our player type for this game."""
class Team(ba.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.score = 0
self.can_attack: bool = False
self.tnt: Optional[TNTBox] = None
# ba_meta export game
class TNTTeamGame(ba.TeamGameActivity[Player, Team]):
"""Football game for teams mode."""
name = 'Heist'
description = 'Get the enemies Ticket Vault!'
announce_player_deaths = True
@classmethod
def get_available_settings(
cls, sessiontype: type[ba.Session]) -> list[ba.Setting]:
settings = [
ba.IntSetting(
'TNT Hitpoints',
min_value=1000,
default=25000,
increment=1000,
),
ba.FloatChoiceSetting(
'Model Type',
choices=[
('TNT Big', 1),
('TNT', 2),
('Puck', 3),
('Snowball', 4),
],
default=1,
),
ba.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
('1 Minute', 60),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600),
('20 Minutes', 1200),
],
default=0,
),
ba.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
('Short', 0.5),
('Normal', 1.0),
('Long', 2.0),
('Longer', 4.0),
],
default=1.0,
),
ba.BoolSetting('Epic Mode', default=False),
]
return settings
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
# We only support two-team play.
return issubclass(sessiontype, ba.DualTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ba.getmaps('team_flag')
def __init__(self, settings: dict):
super().__init__(settings)
self._time_limit = float(settings['Time Limit'])
self._tnt_hitpoints = int(settings['TNT Hitpoints'])
self._model_type = float(settings['Model Type'])
self._tntbox_pos = [(-11, 2.5, 0.0), (11.0, 2.5, 0.0)]
self.team_index = 1
self.create_team_index = 1
self._bots = SpazBotSet()
def get_instance_description(self) -> Union[str, Sequence]:
return 'Get the enemies Ticket Vault!'
def get_instance_description_short(self) -> Union[str, Sequence]:
return 'Get the enemies Ticket Vault!'
def on_team_join(self, team: Team) -> None:
# Can't do this in create_team because the team's color/etc. have
# not been wired up yet at that point.
self._spawn_tnt_for_team(team)
def _spawn_tnt_for_team(self, team: Team) -> None:
team.tnt = TNTBox(team_id=team,
modeltype=self._model_type,
position=self.map.get_flag_position(team.id),
hitpoints=self._tnt_hitpoints,
team='team ' + str(self.team_index)).autoretain()
self.team_index += 1
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self._time_limit)
ba.timer(0.05, self._update, repeat=True)
ba.timer(10.0, self.custom_drop, repeat=True)
# self.setup_standard_powerup_drops()
def custom_drop(self):
pos = self.map.get_flag_position(None)
def spawn_punch():
PowerupBox(
position=(pos[0], pos[1] + 2.0, pos[2]),
poweruptype='punch',
expire=False).autoretain()
def spawn_shield():
PowerupBox(
position=(pos[0], pos[1] + 2.0, pos[2]),
poweruptype='shield',
expire=False).autoretain()
def spawn_explodeybot():
self._bots._spawn_bot(
ExplodeyBotNoTimeLimit,
pos=(pos[0], pos[1] + 1.0, pos[2]),
on_spawn_call=None)
custom = random.choice([spawn_punch, spawn_shield, spawn_explodeybot])
spawner.Spawner(
pt=pos,
spawn_time=3.0,
send_spawn_message=False,
spawn_callback=custom)
def _update(self) -> None:
if not self.teams[0].tnt.node:
self.teams[1].score = 1
if not self.teams[1].tnt.node:
self.teams[0].score = 1
if self.teams[0].score > 0 or self.teams[1].score > 0:
ba.timer(1.0, self.end_game)
def spawn_player(self, player: Player) -> ba.Actor:
team: Team = player.team
spaz = self.spawn_player_spaz(player)
spaz.connect_controls_to_player(enable_bomb=False)
return spaz
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
# Augment standard behavior.
super().handlemessage(msg)
player = msg.getplayer(Player)
self.respawn_player(player)
else:
return super().handlemessage(msg)
return None
def end_game(self) -> None:
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results, announce_delay=0.8)

1551
dist/ba_root/mods/games/Hot-Bomb.py vendored Normal file

File diff suppressed because it is too large Load diff

BIN
dist/ba_root/mods/games/LaserTracer.so vendored Normal file

Binary file not shown.

View file

@ -936,65 +936,3 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
class MGdefs():
points = {}
boxes = {}
points['flag_default'] = (0.17358, 3.75764, 1.99124)
boxes['area_of_interest_bounds'] = (0.3544110667, 4.493562578, -2.518391331) + (0.0, 0.0, 0.0) + (16.64754831, 8.06138989, 18.5029888)
boxes['map_bounds'] = (0.2608783669, 4.899663734, -3.543675157) + (0.0, 0.0, 0.0) + (29.23565494, 14.19991443, 29.92689344)
class MGmap(ba.Map):
defs = MGdefs()
name = 'Sky Tiles'
@classmethod
def get_play_types(cls) -> List[str]:
"""Return valid play types for this map."""
return []
@classmethod
def get_preview_texture_name(cls) -> str:
return 'achievementOffYouGo'
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'bgtex': ba.gettexture('menuBG'),
'bgmodel': ba.getmodel('thePadBG')
}
return data
def __init__(self) -> None:
super().__init__()
shared = SharedObjects.get()
self.node = ba.newnode(
'terrain',
attrs={
'model': self.preloaddata['bgmodel'],
'lighting': False,
'background': True,
'color_texture': self.preloaddata['bgtex']
})
gnode = ba.getactivity().globalsnode
gnode.tint = (1.3, 1.2, 1.0)
gnode.ambient_color = (1.3, 1.2, 1.0)
gnode.vignette_outer = (0.57, 0.57, 0.57)
gnode.vignette_inner = (0.9, 0.9, 0.9)
gnode.vr_camera_offset = (0, -0.8, -1.1)
gnode.vr_near_clip = 0.5
# Plugin only for our map UwU
# ba_meta export plugin
class byFreaku(ba.Plugin):
def on_app_launch(self):
ba._map.register_map(MGmap)

233
dist/ba_root/mods/games/MusicalFlags.py vendored Normal file
View file

@ -0,0 +1,233 @@
## Made by MattZ45986 on GitHub
## Ported by: Freaku / @[Just] Freak#4999
#Bug Fixes & Improvements as well...
#Join BCS:
# https://discord.gg/ucyaesh
from __future__ import annotations
from typing import TYPE_CHECKING
import _ba,ba,random,math
from bastd.actor.flag import Flag,FlagPickedUpMessage
from bastd.actor.playerspaz import PlayerSpaz
if TYPE_CHECKING:
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
class Player(ba.Player['Team']):
def __init__(self) -> None:
self.done: bool = False
self.survived: bool = True
class Team(ba.Team[Player]):
def __init__(self) -> None:
self.score = 0
# ba_meta require api 6
# ba_meta export game
class MFGame(ba.TeamGameActivity[Player, Team]):
name = 'Musical Flags'
description = "Don't be the one stuck without a flag!"
@classmethod
def get_available_settings(
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
settings = [
ba.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
('1 Minute', 60),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600),
('20 Minutes', 1200),
],
default=0,
),
ba.BoolSetting('Epic Mode', default=False),
ba.BoolSetting('Enable Running', default=True),
ba.BoolSetting('Enable Punching', default=False),
ba.BoolSetting('Enable Bottom Credit', True)
]
return settings
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return (issubclass(sessiontype, ba.DualTeamSession)
or issubclass(sessiontype, ba.FreeForAllSession))
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ['Doom Shroom']
def __init__(self, settings: dict):
super().__init__(settings)
self.nodes = []
self._dingsound = ba.getsound('dingSmall')
self._epic_mode = bool(settings['Epic Mode'])
self.credit_text = bool(settings['Enable Bottom Credit'])
self._time_limit = float(settings['Time Limit'])
self.is_punch = bool(settings['Enable Punching'])
self.is_run = bool(settings['Enable Running'])
self._textRound = ba.newnode('text',
attrs={'text': '',
'position': (0, -38),
'scale': 1,
'shadow': 1.0,
'flatness': 1.0,
'color': (1.0, 0.0, 1.0),
'opacity': 1,
'v_attach': 'top',
'h_attach': 'center',
'h_align': 'center',
'v_align': 'center'})
self.slow_motion = self._epic_mode
# A cool music, matching our gamemode theme
self.default_music = ba.MusicType.FLAG_CATCHER
def get_instance_description(self) -> Union[str, Sequence]:
return 'Catch Flag for yourself'
def get_instance_description_short(self) -> Union[str, Sequence]:
return 'Catch Flag for yourself'
def on_player_join(self, player: Player) -> None:
if self.has_begun():
ba.screenmessage(
ba.Lstr(resource='playerDelayedJoinText',
subs=[('${PLAYER}', player.getname(full=True))]),
color=(0, 1, 0),transient=True)
player.survived = False
return
self.spawn_player(player)
def on_player_leave(self, player: Player) -> None:
super().on_player_leave(player)
# A departing player may trigger game-over.
self.checkEnd()
def on_begin(self) -> None:
super().on_begin()
self.roundNum = 0
self.numPickedUp = 0
self.nodes = []
self.flags = []
self.spawned = []
self.setup_standard_time_limit(self._time_limit)
import base64
exec(base64.b64decode("aWYgc2VsZi5jcmVkaXRfdGV4dDoKICAgICMjIFBlb3BsZSBzdGVhbGVkIGNyZWRpdHMgc28gdGhhdHMgd2h5IEkgZW5jb2RlZCB0aGlzLi4uCiAgICAjIyBFdmVuIHRobyB0aGVyZSBpcyBhIG9wdGlvbiwgdGhleSBjaGFuZ2VkIGNyZWF0ZWQgYnkKICAgICMjIGxpa2Ugd3RmIGlzIHRoaWVyIHByb2JsZW0/PwoKICAgICMjIEFueXdheXMgaGF2ZSBhIGdvb2QgZGF5IQogICAgdCA9IGJhLm5ld25vZGUoJ3RleHQnLAogICAgICAgICAgICAgICBhdHRycz17ICd0ZXh0JzoiUG9ydGVkIGJ5IO6BiEZyZWFrdVxuTWFkZSBieSBNYXR0WjQ1OTg2IiwgIyMgRGlzYWJsZSAnRW5hYmxlIEJvdHRvbSBDcmVkaXRzJyB3aGVuIG1ha2luZyBwbGF5bGlzdCwgTm8gbmVlZCB0byBlZGl0IHRoaXMgbG92ZWx5Li4uCiAgICAgICAgJ3NjYWxlJzowLjcsCiAgICAgICAgJ3Bvc2l0aW9uJzooMCwwKSwKICAgICAgICAnc2hhZG93JzowLjUsCiAgICAgICAgJ2ZsYXRuZXNzJzoxLjIsCiAgICAgICAgJ2NvbG9yJzooMSwgMSwgMSksCiAgICAgICAgJ2hfYWxpZ24nOidjZW50ZXInLAogICAgICAgICd2X2F0dGFjaCc6J2JvdHRvbSd9KQ==").decode('UTF-8'))
self.makeRound()
self._textRound.text = 'Round ' + str(self.roundNum)
ba.timer(5, self.checkEnd)
def makeRound(self):
for player in self.players:
if player.survived: player.team.score += 1
self.roundNum += 1
self._textRound.text = 'Round ' + str(self.roundNum)
self.flags = []
self.spawned = []
angle = random.randint(0,359)
c=0
for player in self.players:
if player.survived: c+=1
spacing = 10
for player in self.players:
player.done = False
if player.survived:
if not player.is_alive():
self.spawn_player(player,(.5,5,-4))
self.spawned.append(player)
try: spacing = 360 // (c)
except: self.checkEnd()
colors = [(1,0,0),(0,1,0),(0,0,1),(1,1,0),(1,0,1),(0,1,1),(0,0,0),(0.5,0.8,0),(0,0.8,0.5),(0.8,0.25,0.7),(0,0.27,0.55),(2,2,0.6),(0.4,3,0.85)]
# Smart Mathematics:
# All Flags spawn same distance from the players
for i in range(c-1):
angle += spacing
angle %= 360
x=6 * math.sin(math.degrees(angle))
z=6 * math.cos(math.degrees(angle))
flag = Flag(position=(x+.5,5,z-4), color=colors[i]).autoretain()
self.flags.append(flag)
def killRound(self):
self.numPickedUp = 0
for player in self.players:
if player.is_alive(): player.actor.handlemessage(ba.DieMessage())
for flag in self.flags: flag.node.delete()
for light in self.nodes: light.delete()
def spawn_player(self, player: Player, pos: tuple = (0,0,0)) -> ba.Actor:
spaz = self.spawn_player_spaz(player)
if pos == (0,0,0):
pos = (-.5+random.random()*2,3+random.random()*2,-5+random.random()*2)
spaz.connect_controls_to_player(enable_punch=self.is_punch, enable_bomb=False, enable_run=self.is_run)
spaz.handlemessage(ba.StandMessage(pos))
return spaz
def check_respawn(self, player):
if not player.done and player.survived:
self.respawn_player(player, 2.5)
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
super().handlemessage(msg)
player = msg.getplayer(Player)
ba.timer(0.1, ba.Call(self.check_respawn, player))
ba.timer(0.5, self.checkEnd)
elif isinstance(msg, FlagPickedUpMessage):
self.numPickedUp += 1
msg.node.getdelegate(PlayerSpaz, True).getplayer(Player, True).done = True
l = ba.newnode('light',
owner=None,
attrs={'color':msg.node.color,
'position':(msg.node.position_center),
'intensity':1})
self.nodes.append(l)
msg.flag.handlemessage(ba.DieMessage())
msg.node.handlemessage(ba.DieMessage())
msg.node.delete()
if self.numPickedUp == len(self.flags):
for player in self.spawned:
if not player.done:
try:
player.survived = False
ba.screenmessage("No Flag? "+player.getname())
player.actor.handlemessage(ba.StandMessage((0,3,-2)))
ba.timer(0.5,ba.Call(player.actor.handlemessage, ba.FreezeMessage()))
ba.timer(3,ba.Call(player.actor.handlemessage, ba.ShouldShatterMessage()))
except: pass
ba.timer(3.5,self.killRound)
ba.timer(3.55,self.makeRound)
else:
return super().handlemessage(msg)
return None
def checkEnd(self):
i = 0
for player in self.players:
if player.survived:
i+=1
if i <= 1:
for player in self.players:
if player.survived:
player.team.score += 10
ba.timer(2.5, self.end_game)
def end_game(self) -> None:
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)

722
dist/ba_root/mods/games/Reverserace.py vendored Normal file
View file

@ -0,0 +1,722 @@
# Released under the MIT License. See LICENSE for details.
#
"""Defines Race mini-game."""
# Created inside BCS (Bombsquad consultancy services)
# discord.gg/ucyaesh
# https://bombsquad.ga
# - Reverse Race by Mr.Smoothy
# ba_meta require api 6
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
import random
from typing import TYPE_CHECKING
from dataclasses import dataclass
import ba
from bastd.actor.bomb import Bomb
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
from bastd.gameutils import SharedObjects
if TYPE_CHECKING:
from typing import (Any, Type, Tuple, List, Sequence, Optional, Dict,
Union)
from bastd.actor.onscreentimer import OnScreenTimer
@dataclass
class RaceMine:
"""Holds info about a mine on the track."""
point: Sequence[float]
mine: Optional[Bomb]
class RaceRegion(ba.Actor):
"""Region used to track progress during a race."""
def __init__(self, pt: Sequence[float], index: int):
super().__init__()
activity = self.activity
assert isinstance(activity, ReverseRaceGame)
self.pos = pt
self.index = index
self.node = ba.newnode(
'region',
delegate=self,
attrs={
'position': pt[:3],
'scale': (pt[3] * 2.0, pt[4] * 2.0, pt[5] * 2.0),
'type': 'box',
'materials': [activity.race_region_material]
})
class Player(ba.Player['Team']):
"""Our player type for this game."""
def __init__(self) -> None:
self.distance_txt: Optional[ba.Node] = None
self.last_region = 0
self.lap = 0
self.distance = 0.0
self.finished = False
self.rank: Optional[int] = None
class Team(ba.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.time: Optional[float] = None
self.lap = 0
self.finished = False
# ba_meta export game
class ReverseRaceGame(ba.TeamGameActivity[Player, Team]):
"""Game of racing around a track."""
name = 'Reverse Race'
description = 'Run real fast! \n but in reverse direction'
scoreconfig = ba.ScoreConfig(label='Time',
lower_is_better=True,
scoretype=ba.ScoreType.MILLISECONDS)
@classmethod
def get_available_settings(
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
settings = [
ba.IntSetting('Laps', min_value=1, default=3, increment=1),
ba.IntChoiceSetting(
'Time Limit',
default=0,
choices=[
('None', 0),
('1 Minute', 60),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600),
('20 Minutes', 1200),
],
),
ba.IntChoiceSetting(
'Mine Spawning',
default=4000,
choices=[
('No Mines', 0),
('8 Seconds', 8000),
('4 Seconds', 4000),
('2 Seconds', 2000),
],
),
ba.IntChoiceSetting(
'Bomb Spawning',
choices=[
('None', 0),
('8 Seconds', 8000),
('4 Seconds', 4000),
('2 Seconds', 2000),
('1 Second', 1000),
],
default=2000,
),
ba.BoolSetting('Epic Mode', default=False),
]
# We have some specific settings in teams mode.
if issubclass(sessiontype, ba.DualTeamSession):
settings.append(
ba.BoolSetting('Entire Team Must Finish', default=False))
return settings
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.MultiTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ba.getmaps('race')
def __init__(self, settings: dict):
self._race_started = False
super().__init__(settings)
self._scoreboard = Scoreboard()
self._score_sound = ba.getsound('score')
self._swipsound = ba.getsound('swip')
self._last_team_time: Optional[float] = None
self._front_race_region: Optional[int] = None
self._nub_tex = ba.gettexture('nub')
self._beep_1_sound = ba.getsound('raceBeep1')
self._beep_2_sound = ba.getsound('raceBeep2')
self.race_region_material: Optional[ba.Material] = None
self._regions: List[RaceRegion] = []
self._team_finish_pts: Optional[int] = None
self._time_text: Optional[ba.Actor] = None
self._timer: Optional[OnScreenTimer] = None
self._race_mines: Optional[List[RaceMine]] = None
self._race_mine_timer: Optional[ba.Timer] = None
self._scoreboard_timer: Optional[ba.Timer] = None
self._player_order_update_timer: Optional[ba.Timer] = None
self._start_lights: Optional[List[ba.Node]] = None
self._bomb_spawn_timer: Optional[ba.Timer] = None
self._laps = int(settings['Laps'])
self._entire_team_must_finish = bool(
settings.get('Entire Team Must Finish', False))
self._time_limit = float(settings['Time Limit'])
self._mine_spawning = int(settings['Mine Spawning'])
self._bomb_spawning = int(settings['Bomb Spawning'])
self._epic_mode = bool(settings['Epic Mode'])
# Base class overrides.
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC_RACE
if self._epic_mode else ba.MusicType.RACE)
def get_instance_description(self) -> Union[str, Sequence]:
if (isinstance(self.session, ba.DualTeamSession)
and self._entire_team_must_finish):
t_str = ' Your entire team has to finish.'
else:
t_str = ''
if self._laps > 1:
return 'Run ${ARG1} laps.' + t_str, self._laps
return 'Run 1 lap.' + t_str
def get_instance_description_short(self) -> Union[str, Sequence]:
if self._laps > 1:
return 'run ${ARG1} laps in reverse direction', self._laps
return 'run 1 lap'
def on_transition_in(self) -> None:
super().on_transition_in()
shared = SharedObjects.get()
pts = self.map.get_def_points('race_point')
mat = self.race_region_material = ba.Material()
mat.add_actions(conditions=('they_have_material',
shared.player_material),
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', False),
('call', 'at_connect',
self._handle_race_point_collide),
))
self._regions.append(RaceRegion(pts[0], len(self._regions)))
pts.reverse()
for rpt in pts[:-1]:
self._regions.append(RaceRegion(rpt, len(self._regions)))
def _flash_player(self, player: Player, scale: float) -> None:
assert isinstance(player.actor, PlayerSpaz)
assert player.actor.node
pos = player.actor.node.position
light = ba.newnode('light',
attrs={
'position': pos,
'color': (1, 1, 0),
'height_attenuated': False,
'radius': 0.4
})
ba.timer(0.5, light.delete)
ba.animate(light, 'intensity', {0: 0, 0.1: 1.0 * scale, 0.5: 0})
def _handle_race_point_collide(self) -> None:
# FIXME: Tidy this up.
# pylint: disable=too-many-statements
# pylint: disable=too-many-branches
# pylint: disable=too-many-nested-blocks
collision = ba.getcollision()
try:
region = collision.sourcenode.getdelegate(RaceRegion, True)
player = collision.opposingnode.getdelegate(PlayerSpaz,
True).getplayer(
Player, True)
except ba.NotFoundError:
return
last_region = player.last_region
this_region = region.index
if last_region != this_region:
# If a player tries to skip regions, smite them.
# Allow a one region leeway though (its plausible players can get
# blown over a region, etc).
if this_region > last_region + 2:
if player.is_alive():
assert player.actor
player.actor.handlemessage(ba.DieMessage())
ba.screenmessage(ba.Lstr(
translate=('statements', 'Killing ${NAME} for'
' skipping part of the track!'),
subs=[('${NAME}', player.getname(full=True))]),
color=(1, 0, 0))
else:
# If this player is in first, note that this is the
# front-most race-point.
if player.rank == 0:
self._front_race_region = this_region
player.last_region = this_region
if last_region >= len(self._regions) - 2 and this_region == 0:
team = player.team
player.lap = min(self._laps, player.lap + 1)
# In teams mode with all-must-finish on, the team lap
# value is the min of all team players.
# Otherwise its the max.
if isinstance(self.session, ba.DualTeamSession
) and self._entire_team_must_finish:
team.lap = min([p.lap for p in team.players])
else:
team.lap = max([p.lap for p in team.players])
# A player is finishing.
if player.lap == self._laps:
# In teams mode, hand out points based on the order
# players come in.
if isinstance(self.session, ba.DualTeamSession):
assert self._team_finish_pts is not None
if self._team_finish_pts > 0:
self.stats.player_scored(player,
self._team_finish_pts,
screenmessage=False)
self._team_finish_pts -= 25
# Flash where the player is.
self._flash_player(player, 1.0)
player.finished = True
assert player.actor
player.actor.handlemessage(
ba.DieMessage(immediate=True))
# Makes sure noone behind them passes them in rank
# while finishing.
player.distance = 9999.0
# If the whole team has finished the race.
if team.lap == self._laps:
ba.playsound(self._score_sound)
player.team.finished = True
assert self._timer is not None
elapsed = ba.time() - self._timer.getstarttime()
self._last_team_time = player.team.time = elapsed
self._check_end_game()
# Team has yet to finish.
else:
ba.playsound(self._swipsound)
# They've just finished a lap but not the race.
else:
ba.playsound(self._swipsound)
self._flash_player(player, 0.3)
# Print their lap number over their head.
try:
assert isinstance(player.actor, PlayerSpaz)
mathnode = ba.newnode('math',
owner=player.actor.node,
attrs={
'input1': (0, 1.9, 0),
'operation': 'add'
})
player.actor.node.connectattr(
'torso_position', mathnode, 'input2')
tstr = ba.Lstr(resource='lapNumberText',
subs=[('${CURRENT}',
str(player.lap + 1)),
('${TOTAL}', str(self._laps))
])
txtnode = ba.newnode('text',
owner=mathnode,
attrs={
'text': tstr,
'in_world': True,
'color': (1, 1, 0, 1),
'scale': 0.015,
'h_align': 'center'
})
mathnode.connectattr('output', txtnode, 'position')
ba.animate(txtnode, 'scale', {
0.0: 0,
0.2: 0.019,
2.0: 0.019,
2.2: 0
})
ba.timer(2.3, mathnode.delete)
except Exception:
ba.print_exception('Error printing lap.')
def on_team_join(self, team: Team) -> None:
self._update_scoreboard()
def on_player_leave(self, player: Player) -> None:
super().on_player_leave(player)
# A player leaving disqualifies the team if 'Entire Team Must Finish'
# is on (otherwise in teams mode everyone could just leave except the
# leading player to win).
if (isinstance(self.session, ba.DualTeamSession)
and self._entire_team_must_finish):
ba.screenmessage(ba.Lstr(
translate=('statements',
'${TEAM} is disqualified because ${PLAYER} left'),
subs=[('${TEAM}', player.team.name),
('${PLAYER}', player.getname(full=True))]),
color=(1, 1, 0))
player.team.finished = True
player.team.time = None
player.team.lap = 0
ba.playsound(ba.getsound('boo'))
for otherplayer in player.team.players:
otherplayer.lap = 0
otherplayer.finished = True
try:
if otherplayer.actor is not None:
otherplayer.actor.handlemessage(ba.DieMessage())
except Exception:
ba.print_exception('Error sending DieMessage.')
# Defer so team/player lists will be updated.
ba.pushcall(self._check_end_game)
def _update_scoreboard(self) -> None:
for team in self.teams:
distances = [player.distance for player in team.players]
if not distances:
teams_dist = 0.0
else:
if (isinstance(self.session, ba.DualTeamSession)
and self._entire_team_must_finish):
teams_dist = min(distances)
else:
teams_dist = max(distances)
self._scoreboard.set_team_value(
team,
teams_dist,
self._laps,
flash=(teams_dist >= float(self._laps)),
show_value=False)
def on_begin(self) -> None:
from bastd.actor.onscreentimer import OnScreenTimer
super().on_begin()
self.setup_standard_time_limit(self._time_limit)
self.setup_standard_powerup_drops()
self._team_finish_pts = 100
# Throw a timer up on-screen.
self._time_text = ba.NodeActor(
ba.newnode('text',
attrs={
'v_attach': 'top',
'h_attach': 'center',
'h_align': 'center',
'color': (1, 1, 0.5, 1),
'flatness': 0.5,
'shadow': 0.5,
'position': (0, -50),
'scale': 1.4,
'text': ''
}))
self._timer = OnScreenTimer()
if self._mine_spawning != 0:
self._race_mines = [
RaceMine(point=p, mine=None)
for p in self.map.get_def_points('race_mine')
]
if self._race_mines:
self._race_mine_timer = ba.Timer(0.001 * self._mine_spawning,
self._update_race_mine,
repeat=True)
self._scoreboard_timer = ba.Timer(0.25,
self._update_scoreboard,
repeat=True)
self._player_order_update_timer = ba.Timer(0.25,
self._update_player_order,
repeat=True)
if self.slow_motion:
t_scale = 0.4
light_y = 50
else:
t_scale = 1.0
light_y = 150
lstart = 7.1 * t_scale
inc = 1.25 * t_scale
ba.timer(lstart, self._do_light_1)
ba.timer(lstart + inc, self._do_light_2)
ba.timer(lstart + 2 * inc, self._do_light_3)
ba.timer(lstart + 3 * inc, self._start_race)
self._start_lights = []
for i in range(4):
lnub = ba.newnode('image',
attrs={
'texture': ba.gettexture('nub'),
'opacity': 1.0,
'absolute_scale': True,
'position': (-75 + i * 50, light_y),
'scale': (50, 50),
'attach': 'center'
})
ba.animate(
lnub, 'opacity', {
4.0 * t_scale: 0,
5.0 * t_scale: 1.0,
12.0 * t_scale: 1.0,
12.5 * t_scale: 0.0
})
ba.timer(13.0 * t_scale, lnub.delete)
self._start_lights.append(lnub)
self._start_lights[0].color = (0.2, 0, 0)
self._start_lights[1].color = (0.2, 0, 0)
self._start_lights[2].color = (0.2, 0.05, 0)
self._start_lights[3].color = (0.0, 0.3, 0)
def _do_light_1(self) -> None:
assert self._start_lights is not None
self._start_lights[0].color = (1.0, 0, 0)
ba.playsound(self._beep_1_sound)
def _do_light_2(self) -> None:
assert self._start_lights is not None
self._start_lights[1].color = (1.0, 0, 0)
ba.playsound(self._beep_1_sound)
def _do_light_3(self) -> None:
assert self._start_lights is not None
self._start_lights[2].color = (1.0, 0.3, 0)
ba.playsound(self._beep_1_sound)
def _start_race(self) -> None:
assert self._start_lights is not None
self._start_lights[3].color = (0.0, 1.0, 0)
ba.playsound(self._beep_2_sound)
for player in self.players:
if player.actor is not None:
try:
assert isinstance(player.actor, PlayerSpaz)
player.actor.connect_controls_to_player()
except Exception:
ba.print_exception('Error in race player connects.')
assert self._timer is not None
self._timer.start()
if self._bomb_spawning != 0:
self._bomb_spawn_timer = ba.Timer(0.001 * self._bomb_spawning,
self._spawn_bomb,
repeat=True)
self._race_started = True
def _update_player_order(self) -> None:
# Calc all player distances.
for player in self.players:
pos: Optional[ba.Vec3]
try:
pos = player.position
except ba.NotFoundError:
pos = None
if pos is not None:
r_index = player.last_region
rg1 = self._regions[r_index]
r1pt = ba.Vec3(rg1.pos[:3])
rg2 = self._regions[0] if r_index == len(
self._regions) - 1 else self._regions[r_index + 1]
r2pt = ba.Vec3(rg2.pos[:3])
r2dist = (pos - r2pt).length()
amt = 1.0 - (r2dist / (r2pt - r1pt).length())
amt = player.lap + (r_index + amt) * (1.0 / len(self._regions))
player.distance = amt
# Sort players by distance and update their ranks.
p_list = [(player.distance, player) for player in self.players]
p_list.sort(reverse=True, key=lambda x: x[0])
for i, plr in enumerate(p_list):
plr[1].rank = i
if plr[1].actor:
node = plr[1].distance_txt
if node:
node.text = str(i + 1) if plr[1].is_alive() else ''
def _spawn_bomb(self) -> None:
if self._front_race_region is None:
return
region = (self._front_race_region + 3) % len(self._regions)
pos = self._regions[region].pos
# Don't use the full region so we're less likely to spawn off a cliff.
region_scale = 0.8
x_range = ((-0.5, 0.5) if pos[3] == 0 else
(-region_scale * pos[3], region_scale * pos[3]))
z_range = ((-0.5, 0.5) if pos[5] == 0 else
(-region_scale * pos[5], region_scale * pos[5]))
pos = (pos[0] + random.uniform(*x_range), pos[1] + 1.0,
pos[2] + random.uniform(*z_range))
ba.timer(random.uniform(0.0, 2.0),
ba.WeakCall(self._spawn_bomb_at_pos, pos))
def _spawn_bomb_at_pos(self, pos: Sequence[float]) -> None:
if self.has_ended():
return
Bomb(position=pos, bomb_type='normal').autoretain()
def _make_mine(self, i: int) -> None:
assert self._race_mines is not None
rmine = self._race_mines[i]
rmine.mine = Bomb(position=rmine.point[:3], bomb_type='land_mine')
rmine.mine.arm()
def _flash_mine(self, i: int) -> None:
assert self._race_mines is not None
rmine = self._race_mines[i]
light = ba.newnode('light',
attrs={
'position': rmine.point[:3],
'color': (1, 0.2, 0.2),
'radius': 0.1,
'height_attenuated': False
})
ba.animate(light, 'intensity', {0.0: 0, 0.1: 1.0, 0.2: 0}, loop=True)
ba.timer(1.0, light.delete)
def _update_race_mine(self) -> None:
assert self._race_mines is not None
m_index = -1
rmine = None
for _i in range(3):
m_index = random.randrange(len(self._race_mines))
rmine = self._race_mines[m_index]
if not rmine.mine:
break
assert rmine is not None
if not rmine.mine:
self._flash_mine(m_index)
ba.timer(0.95, ba.Call(self._make_mine, m_index))
def spawn_player(self, player: Player) -> ba.Actor:
if player.team.finished:
# FIXME: This is not type-safe!
# This call is expected to always return an Actor!
# Perhaps we need something like can_spawn_player()...
# noinspection PyTypeChecker
return None # type: ignore
pos = self._regions[player.last_region].pos
# Don't use the full region so we're less likely to spawn off a cliff.
region_scale = 0.8
x_range = ((-0.5, 0.5) if pos[3] == 0 else
(-region_scale * pos[3], region_scale * pos[3]))
z_range = ((-0.5, 0.5) if pos[5] == 0 else
(-region_scale * pos[5], region_scale * pos[5]))
pos = (pos[0] + random.uniform(*x_range), pos[1],
pos[2] + random.uniform(*z_range))
spaz = self.spawn_player_spaz(
player, position=pos, angle=270 if not self._race_started else None)
assert spaz.node
# Prevent controlling of characters before the start of the race.
if not self._race_started:
spaz.disconnect_controls_from_player()
mathnode = ba.newnode('math',
owner=spaz.node,
attrs={
'input1': (0, 1.4, 0),
'operation': 'add'
})
spaz.node.connectattr('torso_position', mathnode, 'input2')
distance_txt = ba.newnode('text',
owner=spaz.node,
attrs={
'text': '',
'in_world': True,
'color': (1, 1, 0.4),
'scale': 0.02,
'h_align': 'center'
})
player.distance_txt = distance_txt
mathnode.connectattr('output', distance_txt, 'position')
return spaz
def _check_end_game(self) -> None:
# If there's no teams left racing, finish.
teams_still_in = len([t for t in self.teams if not t.finished])
if teams_still_in == 0:
self.end_game()
return
# Count the number of teams that have completed the race.
teams_completed = len(
[t for t in self.teams if t.finished and t.time is not None])
if teams_completed > 0:
session = self.session
# In teams mode its over as soon as any team finishes the race
# FIXME: The get_ffa_point_awards code looks dangerous.
if isinstance(session, ba.DualTeamSession):
self.end_game()
else:
# In ffa we keep the race going while there's still any points
# to be handed out. Find out how many points we have to award
# and how many teams have finished, and once that matches
# we're done.
assert isinstance(session, ba.FreeForAllSession)
points_to_award = len(session.get_ffa_point_awards())
if teams_completed >= points_to_award - teams_completed:
self.end_game()
return
def end_game(self) -> None:
# Stop updating our time text, and set it to show the exact last
# finish time if we have one. (so users don't get upset if their
# final time differs from what they see onscreen by a tiny amount)
assert self._timer is not None
if self._timer.has_started():
self._timer.stop(
endtime=None if self._last_team_time is None else (
self._timer.getstarttime() + self._last_team_time))
results = ba.GameResults()
for team in self.teams:
if team.time is not None:
# We store time in seconds, but pass a score in milliseconds.
results.set_team_score(team, int(team.time * 1000.0))
else:
results.set_team_score(team, None)
# We don't announce a winner in ffa mode since its probably been a
# while since the first place guy crossed the finish line so it seems
# odd to be announcing that now.
self.end(results=results,
announce_winning_team=isinstance(self.session,
ba.DualTeamSession))
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
# Augment default behavior.
super().handlemessage(msg)
player = msg.getplayer(Player)
if not player.finished:
self.respawn_player(player, respawn_time=1)
else:
super().handlemessage(msg)

395
dist/ba_root/mods/games/Tower_Rush.py vendored Normal file
View file

@ -0,0 +1,395 @@
# Released under the MIT License. See LICENSE for details.
#
"""Defines assault minigame."""
# ba_meta require api 6
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING
import ba, random
from math import cos, sin
from bastd.actor.popuptext import PopupText
from bastd.actor.powerupbox import PowerupBox, PowerupBoxFactory
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
from bastd.gameutils import SharedObjects
if TYPE_CHECKING:
from typing import Any, Type, List, Dict, Sequence, Union
class Player(ba.Player['Team']):
...
class Team(ba.Team[Player]):
def __init__(self) -> None:
self.score = 0
self.stored_score = 0
self.role: str = ''
self.spot: str = ''
# ba_meta export game
class BaseRaidGame(ba.TeamGameActivity[Player, Team]):
name = 'Tower Rush'
description = """If "score" is shown on your character,\ngo through inside the enemy team's castle-like structure\nto score. Otherwise if "defend" is shown\nprevent the enemy team from entering."""
available_settings = [
ba.IntSetting('Score to Win Per Team', min_value=1, default=10),
ba.IntChoiceSetting('Time Limit',
choices=[
('None', 0),
('1 Minute', 60),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600),
('20 Minutes', 1200)],
default=300),
ba.IntSetting('Countdown Time Each Round', min_value = 10, increment=5 ,default = 60),
ba.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
('Short', 0.5),
('Normal', 1.0),
('Long', 2.0),
('Longer', 4.0)],
default=1.0),
ba.BoolSetting('Epic Mode', default=False),
ba.BoolSetting('Kill player on ground', default=True),
ba.BoolSetting('Random Spawn Point (Team)', default=False),
ba.BoolSetting('[On score] Single Teleport', default=True),
ba.BoolSetting('[On score] Single Celebrate', default=True)]
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.DualTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ['Tower D']
def get_instance_scoreboard_display_string(self) -> ba.Lstr:
return "Score " + str(self._score_to_win) + " Points"
def get_instance_description(self) -> Union[str, Sequence]:
return "if Score, score by reaching through the foe's structure\nif Defend, prevent enemy from scoring."
def __init__(self, settings: dict):
super().__init__(settings)
self.get_s = settings
self._scoreboard = Scoreboard()
self._last_score_time = 0.0
self._score_sound = ba.getsound('score')
self._epic_mode = bool(settings['Epic Mode'])
self._score_to_win = int(settings['Score to Win Per Team'])
self._time_limit = float(settings['Time Limit'])
self.time = int(settings['Countdown Time Each Round'])
self.change_spawn_points = bool(settings['Random Spawn Point (Team)'])
self.ground = bool(settings['Kill player on ground'])
self.loop_timer = self.knocker = None
self.disable_controls = bool(True)
# Base class overrides
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
ba.MusicType.FORWARD_MARCH)
def on_team_join(self, team: Team) -> None:
self._update_scoreboard()
def on_player_join(self, player: PlayerType) -> None:
if not self.disable_controls:
self.spawn_player(player)
else:
pass
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_powerup_drops()
palyer = SharedObjects.get().player_material
death_material = ba.Material(); box_1 = ba.Material(); box_2 = ba.Material()
death_material.add_actions(
conditions=('they_have_material', palyer),
actions=(('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', False),
('call', 'at_connect', ba.WeakCall(self.handle_region, 'ground'))))
box_1.add_actions(
conditions=('they_have_material', palyer),
actions=(('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', False),
('call', 'at_connect', ba.WeakCall(self.handle_region, 'turret_1'))))
box_2.add_actions(
conditions=('they_have_material', palyer),
actions=(('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', False),
('call', 'at_connect', ba.WeakCall(self.handle_region, 'turret_2'))))
self.r: List[ba.NodeActor] = []
self.r.append(ba.NodeActor(ba.newnode('region',
attrs={'position': (-8.450964, 4.784977, 0.300695),
'scale': (0.2, 3.45, 1.28),
'type': 'box',
'materials':[box_1]})))
self.r.append(ba.NodeActor(ba.newnode('region',
attrs={'position': (7.470666, 3.429754, 0.328592),
'scale': (0.2, 2.47, 1.39),
'type': 'box',
'materials':[box_2]})))
if self.ground:
self.r.append(ba.NodeActor(ba.newnode('region',
attrs={'position': (-0.588583, 1.569668, 4.049047),
'scale': (18.0, 0.1, 5.0),
'type': 'box',
'materials':[death_material]})))
self.r.append(ba.NodeActor(ba.newnode('region',
attrs={'position': (-0.128583, 1.569668, -1.670954),
'scale': (5.0, 0.1, 7.0),
'type': 'box',
'materials':[death_material]})))
self.r_timer = ba.newnode('text',
attrs={
'v_attach': 'top',
'h_attach': 'center',
'h_align': 'center',
'color': (0.7,0.88,1.0,1.1),
'shadow': 1.0,
'flatness': 1.0,
'position': (0, -120),
'scale': 1.7,
'text': "..."})
self.setup_standard_time_limit(self._time_limit)
ba.timer(4.5, ba.WeakCall(self.selection, first_run = True))
teams = []
for t in self.teams:
teams.append(t)
roles = ['raid', 'defend']
if self.change_spawn_points:
spots = ['spot2','spot1']
teams[0].spot = spots[random.randint(0,1)]
spots.remove(teams[0].spot)
teams[1].spot = spots[0]
else:
teams[0].spot = 'spot1'
teams[1].spot = 'spot2'
teams[0].role = roles[random.randint(0, 1)]
roles.remove(teams[0].role)
teams[1].role = roles[0]
def launch():
for t in self.teams:
if t.role == 'raid':
ba.screenmessage(t.name.evaluate() + " Team, will be the goaler", color=t.color)
elif t.role == 'defend':
ba.screenmessage(t.name.evaluate() + " Team, will be the defender", color=t.color)
ba.timer(1.9, launch)
def knock_players(self) -> None:
for p in self.players:
if p.is_alive():
p.actor.node.handlemessage('knockout', 800.0)
def decrease(self) -> None:
if int(self.time) != 0:
self.time -= 1
self.r_timer.text = "Round Time: " + str(self.time)
else:
self.loop_timer = None
self.disable_controls = True
self.r_timer.text = "Round Ended"
self.knock_players()
self.knocker = ba.Timer(0.8, ba.Call(self.knock_players), repeat=True)
ba.timer(1, lambda: self.selection())
def get_pos(self, player: Player, center: bool = False) -> None:
ang = random.randint(0, 360)
rad = random.uniform(0, 2.0) if not center else 0.0
y = random.uniform(0.9, 1.16)
if player.team.spot == 'spot1':
x = cos(ang) * rad
z = sin(ang) * rad
pos = (-5.786582 + x, 2.8651068 + y, -0.7751054 + z)
elif player.team.spot == 'spot2':
ang = random.randint(0, 360)
rad = random.uniform(0, 2.0)
x = cos(ang) * rad
z = sin(ang) * rad
pos = (4.37031 + x, 2.51977 + y, -0.1901849 + z)
return pos
def selection(self, first_run: bool = False) -> None:
def scene():
self.disable_controls = True
teams = []
for team in self.teams:
teams.append(team)
spots = ['spot1', 'spot2']
if self.change_spawn_points:
teams[0].spot = spots[random.randint(0, 1)]
spots.remove(teams[0].spot)
teams[1].spot = spots[0]
if not first_run:
temp2 = teams[0].role
teams[0].role = teams[1].role
teams[1].role = temp2
def func():
for t in self.teams:
if not first_run:
if t.role == 'raid':
ba.screenmessage(
"It's now " + t.name.evaluate() + " Team's turn, to score. ",
color=(0.5, 0.8, 0.8))
break
ba.timer(0.926, func)
def scene_2():
for t in self.teams:
t.stored_score = 0
for p in self.players:
if p.actor is None:
self.spawn_player(p)
elif p.is_alive():
p.actor.handlemessage(ba.StandMessage(position=self.get_pos(p), angle=random.uniform(0, 360)))
def delay():
for get_s in self.players:
if get_s.is_alive():
if get_s.team.role == 'raid':
PopupText(position=get_s.actor.node.position, text="Score!", color=get_s.team.color, scale=1.5).autoretain()
else:
PopupText(position=get_s.actor.node.position, text="Defend!", color=get_s.team.color, scale=1.5).autoretain()
self.r_timer.text = "Round Time: " + str(self.time)
self.disable_controls = False
def a(): self.knocker = None
ba.timer(0.9, a)
ba.timer(0.488 if first_run else 0.67, delay)
self.time = self.get_s['Countdown Time Each Round']
self.loop_timer = ba.Timer(1, ba.Call(self.decrease), repeat=True)
def text():
for team in self.teams:
if not first_run:
if team.role == 'raid':
ba.screenmessage(
team.name.evaluate() + " Team secured " + str(team.stored_score) + " goals in " + str(self.get_s["Countdown Time Each Round"]) + " seconds.",
color=(0.4, 0.6, 1.0)
)
break
ba.timer(1.033, text)
ba.timer(2, scene)
ba.timer(4.858 if not first_run else 3, scene_2)
def spawn_player(self, player: Player) -> ba.Actor:
spaz = self.spawn_player_spaz(player, position=self.get_pos(player))
return spaz
def teleport(self, player: Player) -> None:
if self.get_s["[On score] Single Teleport"]:
for this in player.team.players:
if this.actor:
this.actor.handlemessage(ba.StandMessage(position=self.get_pos(this), angle=random.uniform(0, 360)))
else:
if player.actor:
player.actor.handlemessage(ba.StandMessage(position=self.get_pos(player), angle=random.uniform(0, 360)))
if self.get_s['[On score] Single Celebrate']:
for this in player.team.players:
if this.actor:
this.actor.handlemessage(ba.CelebrateMessage(2.0))
else:
if player.actor:
player.actor.handlemessage(ba.CelebrateMessage(2.0))
self.stats.player_scored(player, 10, big_message=True)
def handle_region(self, region: str) -> None:
try:
player = ba.getcollision().opposingnode.getdelegate(
PlayerSpaz, True).getplayer(Player, True)
except: return
if region == 'ground' and not self.disable_controls:
def delay():
player.actor.handlemessage(ba.DieMessage())
ba.timer(10*0.001, delay)
elif region == 'turret_2':
if player.is_alive():
if player.team.role == 'raid' and player.team.spot != 'spot2':
if ba.time() != self._last_score_time:
self._last_score_time = ba.time()
ba.playsound(self._score_sound)
player.team.score += 1
player.team.stored_score += 1
self._update_scoreboard()
self.teleport(player)
else:
return
elif region == 'turret_1':
if player.is_alive():
if player.team.role == 'raid' and player.team.spot != 'spot1':
if ba.time() != self._last_score_time:
self._last_score_time = ba.time()
ba.playsound(self._score_sound)
player.team.score += 1
player.team.stored_score += 1
self._update_scoreboard()
self.teleport(player)
def _standard_drop_powerup(self, index: int, expire: bool = True) -> None:
self.i = [(6.1527314, 4.9323297, -7.8393626),
(-6.8911242, 4.4702456, -7.8909187),
(-5.3111238, 3.930246, -6.170918),
(3.9788754, 3.8102467, -5.9009175),
(-4.926642821, 2.397645612, 2.876782366),
(-1.964335546, 2.397645612, 3.751374716),
(1.64883201, 2.397645612, 3.751374716),
(4.398865293, 2.397645612, 2.877618924)]
self.i = ([p[:3] for p in self.i])
PowerupBox(
position=self.i[index],
poweruptype=PowerupBoxFactory.get().get_random_powerup_type(),
expire=expire).autoretain()
def _standard_drop_powerups(self) -> None:
for i in range(4 if self.ground else 8):
ba.timer(i * 0.4, ba.WeakCall(self._standard_drop_powerup, i))
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
self.respawn_player(msg.getplayer(Player))
else:
super().handlemessage(msg)
return None
def end_game(self) -> None:
self.loop_timer = self.knocker = None
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)
def _update_scoreboard(self) -> None:
for team in self.teams:
self._scoreboard.set_team_value(team, team.score,
self._score_to_win)
if team.score >= self._score_to_win:
self.end_game()

537
dist/ba_root/mods/games/VolleyBall.py vendored Normal file
View file

@ -0,0 +1,537 @@
from __future__ import annotations
#Volley Ball (updated)
#Made for 1.6 by your friend: @[Just] Freak#4999
"""Defines Volley Ball mini-game"""
## This thing was originally made for 1.4 by someone (but had errors/bugs/missing features) so I edited/ported to 1.6/added all useful features :D
## I suggest to join this discord servers:
## https://discord.gg/ucyaesh
## https://discord.gg/NCvfPG2N9A
## Made on Android with the help of Terminal.py
## https://github.com/FreakOPP/BombSquad-Mods-byFREAK/blob/main/Utilities/Terminal.py
## MY (Freak's) comments are double-tagged btw ##
## UPDATED:
"""
- Fixed Puck's mass/size/positions/texture/effects
- Fixed Goal positions
- Better center wall
- Added 1 more map
- Added more customisable options
- Map lights locators are now looped (thus reducing the size of the file and lengthy work...)
- Merged map & minigame in one file
- Puck spawns according to scored team (if right team scored, ball will spawn on left side)
- Also puck now spawns in airrr
- Server support added :)
- Fixed **LOTS** of errors/bugs
"""
# ba_meta require api 6
from typing import TYPE_CHECKING
import bastd, _ba, ba, random
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
from bastd.actor.powerupbox import PowerupBoxFactory
from bastd.gameutils import SharedObjects
if TYPE_CHECKING:
from typing import Any, Sequence, Dict, Type, List, Optional, Union
class PuckDiedMessage:
"""Inform something that a puck has died."""
def __init__(self, puck: Puck):
self.puck = puck
class Puck(ba.Actor):
"""A lovely giant hockey puck."""
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)):
super().__init__()
shared = SharedObjects.get()
activity = self.getactivity()
# Spawn just above the provided point.
self._spawn_pos = (position[0], position[1] + 1.8, position[2])
self.last_players_to_touch: Dict[int, Player] = {}
self.scored = False
assert activity is not None
assert isinstance(activity, VolleyBallGame)
pmats = [shared.object_material, activity.puck_material]
self.node = ba.newnode('prop',
delegate=self,
attrs={
'model': activity.puck_model,
'color_texture': activity.puck_tex,
'body': 'sphere',
'reflection': 'soft',
'reflection_scale': [0.2],
'shadow_size': 0.6,
'model_scale': 0.4,
'body_scale': 1.07,
'is_area_of_interest': True,
'position': self._spawn_pos,
'materials': pmats
})
## Since it rolls on spawn, lets make gravity
## to 0, and when another node (bomb/spaz)
## touches it. It'll act back as our normie puck!
ba.animate(self.node, 'gravity_scale', {0:-0.1, 2:1}, False)
## When other node touches, it realises its new gravity_scale
## Jugad for now...
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
assert self.node
self.node.delete()
activity = self._activity()
if activity and not msg.immediate:
activity.handlemessage(PuckDiedMessage(self))
# If we go out of bounds, move back to where we started.
elif isinstance(msg, ba.OutOfBoundsMessage):
assert self.node
self.node.position = self._spawn_pos
elif isinstance(msg, ba.HitMessage):
assert self.node
assert msg.force_direction is not None
self.node.handlemessage(
'impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0],
msg.velocity[1], msg.velocity[2], 1.0 * msg.magnitude,
1.0 * msg.velocity_magnitude, msg.radius, 0,
msg.force_direction[0], msg.force_direction[1],
msg.force_direction[2])
# If this hit came from a player, log them as the last to touch us.
s_player = msg.get_source_player(Player)
if s_player is not None:
activity = self._activity()
if activity:
if s_player in activity.players:
self.last_players_to_touch[s_player.team.id] = s_player
else:
super().handlemessage(msg)
class Player(ba.Player['Team']):
"""Our player type for this game."""
class Team(ba.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.score = 0
# ba_meta export game
class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
"""Volley Ball game."""
name = 'Volley Ball'
description = 'Score some goals.\nbyFREAK'
available_settings = [
ba.IntSetting(
'Score to Win',
min_value=1,
default=1,
increment=1,
),
ba.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
('1 Minute', 60),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600),
('20 Minutes', 1200),
],
default=0,
),
ba.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
('Short', 0.5),
('Normal', 1.0),
('Long', 2.0),
('Longer', 4.0),
],
default=1.0,
),
ba.BoolSetting('Epic Mode', True),
ba.BoolSetting('Night Mode', False),
ba.BoolSetting('Icy Floor', True),
ba.BoolSetting('Disable Punch', False),
ba.BoolSetting('Disable Bombs', False),
ba.BoolSetting('Enable Bottom Credits', True),
]
default_music = ba.MusicType.HOCKEY
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.DualTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ['Open Field','Closed Arena']
def __init__(self, settings: dict):
super().__init__(settings)
shared = SharedObjects.get()
self._scoreboard = Scoreboard()
self._cheer_sound = ba.getsound('cheer')
self._chant_sound = ba.getsound('crowdChant')
self._foghorn_sound = ba.getsound('foghorn')
self._swipsound = ba.getsound('swip')
self._whistle_sound = ba.getsound('refWhistle')
self.puck_model = ba.getmodel('shield')
self.puck_tex = ba.gettexture('gameCircleIcon')
self._puck_sound = ba.getsound('metalHit')
self.puck_material = ba.Material()
self.puck_material.add_actions(actions=(('modify_part_collision',
'friction', 0.5)))
self.puck_material.add_actions(conditions=('they_have_material',
shared.pickup_material),
actions=('modify_part_collision',
'collide', True))
self.puck_material.add_actions(
conditions=(
('we_are_younger_than', 100),
'and',
('they_have_material', shared.object_material),
),
actions=('modify_node_collision', 'collide', False),
)
self.puck_material.add_actions(conditions=('they_have_material',
shared.footing_material),
actions=('impact_sound',
self._puck_sound, 0.2, 5))
# Keep track of which player last touched the puck
self.puck_material.add_actions(
conditions=('they_have_material', shared.player_material),
actions=(('call', 'at_connect',
self._handle_puck_player_collide), ))
# We want the puck to kill powerups; not get stopped by them
self.puck_material.add_actions(
conditions=('they_have_material',
PowerupBoxFactory.get().powerup_material),
actions=(('modify_part_collision', 'physical', False),
('message', 'their_node', 'at_connect', ba.DieMessage())))
self._score_region_material = ba.Material()
self._score_region_material.add_actions(
conditions=('they_have_material', self.puck_material),
actions=(('modify_part_collision', 'collide',
True), ('modify_part_collision', 'physical', False),
('call', 'at_connect', self._handle_score)))
self._wall_material=ba.Material()
self._fake_wall_material=ba.Material()
self._wall_material.add_actions(
actions=(
('modify_part_collision', 'friction', 100000),
))
self._wall_material.add_actions(
conditions=('they_have_material', shared.pickup_material),
actions=(
('modify_part_collision', 'collide', False),
))
self._wall_material.add_actions(
conditions=(('we_are_younger_than', 100),
'and',
('they_have_material',shared.object_material)),
actions=(
('modify_part_collision', 'collide', False),
))
self._wall_material.add_actions(
conditions=('they_have_material',shared.footing_material),
actions=(
('modify_part_collision', 'friction', 9999.5),
))
self._wall_material.add_actions(
conditions=('they_have_material', bastd.actor.bomb.BombFactory.get().blast_material),
actions=(
('modify_part_collision', 'collide', False),
('modify_part_collision', 'physical', False)
))
self._fake_wall_material.add_actions(
conditions=('they_have_material', shared.player_material),
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)
))
self.blocks=[]
self._net_wall_material=ba.Material()
self._net_wall_material.add_actions(
conditions=('they_have_material', shared.player_material),
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)
))
self._net_wall_material.add_actions(
conditions=('they_have_material', shared.object_material),
actions=(
('modify_part_collision', 'collide', True),
))
self._net_wall_material.add_actions(
conditions=('they_have_material', self.puck_material),
actions=(
('modify_part_collision', 'collide', True),
))
self._net_wall_material.add_actions(
conditions=('we_are_older_than', 1),
actions=(
('modify_part_collision', 'collide', True),
))
self.net_blocc=[]
self._puck_spawn_pos: Optional[Sequence[float]] = None
self._score_regions: Optional[List[ba.NodeActor]] = None
self._puck: Optional[Puck] = None
self._score_to_win = int(settings['Score to Win'])
self._punchie_ = bool(settings['Disable Punch'])
self._night_mode = bool(settings['Night Mode'])
self._bombies_ = bool(settings['Disable Bombs'])
self._time_limit = float(settings['Time Limit'])
self._icy_flooor = bool(settings['Icy Floor'])
self.credit_text = bool(settings['Enable Bottom Credits'])
self._epic_mode = bool(settings['Epic Mode'])
# Base class overrides.
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
ba.MusicType.TO_THE_DEATH)
def get_instance_description(self) -> Union[str, Sequence]:
if self._score_to_win == 1:
return 'Score a goal.'
return 'Score ${ARG1} goals.', self._score_to_win
def get_instance_description_short(self) -> Union[str, Sequence]:
if self._score_to_win == 1:
return 'score a goal'
return 'score ${ARG1} goals', self._score_to_win
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self._time_limit)
if self._night_mode:
ba.getactivity().globalsnode.tint = (0.5, 0.7, 1)
else:
pass
self._puck_spawn_pos = self.map.get_flag_position(None)
self._spawn_puck()
# Set up the two score regions.
defs = self.map.defs
self._score_regions = []
self._score_regions.append(
ba.NodeActor(
ba.newnode('region',
attrs={
'position':(5,0,0),
'scale': defs.boxes['goal1'],
'type': 'box',
'materials': [self._score_region_material]
})))
self._score_regions.append(
ba.NodeActor(
ba.newnode('region',
attrs={
'position':(-5,0,0),
'scale': defs.boxes['goal2'],
'type': 'box',
'materials': [self._score_region_material]
})))
self._update_scoreboard()
ba.playsound(self._chant_sound)
import base64
exec(base64.b64decode("aWYgc2VsZi5jcmVkaXRfdGV4dDoKICAgICMjIFBlb3BsZSBzdGVhbGVkIGNyZWRpdHMgc28gdGhhdHMgd2h5IEkgZW5jb2RlZCB0aGlzLi4uCiAgICAjIyBFdmVuIHRobyB0aGVyZSBpcyBhIG9wdGlvbiwgdGhleSBjaGFuZ2VkIGNyZWF0ZWQgYnkKICAgICMjIGxpa2Ugd3RmIGlzIHRoaWVyIHByb2JsZW0/PwogICAgCiAgICAjIyBBbnl3YXlzIGhhdmUgYSBnb29kIGRheSEKICAgIHQgPSBiYS5uZXdub2RlKCd0ZXh0JywKICAgICAgICAgICAgICAgYXR0cnM9eyAndGV4dCc6IkNyZWF0ZWQgYnkg7oGIRnJlYWt1XG5Wb2xsZXlCYWxsIDEuNiIsICMjIERpc2FibGUgJ0VuYWJsZSBCb3R0b20gQ3JlZGl0cycgd2hlbiBtYWtpbmcgcGxheWxpc3QsIE5vIG5lZWQgdG8gZWRpdCB0aGlzIGxvdmVseS4uLgogICAgICAgICdzY2FsZSc6MC43LAogICAgICAgICdwb3NpdGlvbic6KDAsMCksICNMZXRzIGhvcGUgaGUgdXNlcyBUViBib3JkZXIgb2Ygc2V0dGluZ3M+R3JhcGhpY3MKICAgICAgICAnc2hhZG93JzowLjUsCiAgICAgICAgJ2ZsYXRuZXNzJzoxLjIsCiAgICAgICAgJ2NvbG9yJzooMSwgMSwgMSksCiAgICAgICAgJ2hfYWxpZ24nOidjZW50ZXInLAogICAgICAgICd2X2F0dGFjaCc6J2JvdHRvbSd9KQ==").decode('UTF-8'))
shared = SharedObjects.get()
self.blocks.append(ba.NodeActor(ba.newnode('region',attrs={'position': (0,2.4,0),'scale': (1,6,20),'type': 'box','materials': (self._fake_wall_material, )})))
self.net_blocc.append(ba.NodeActor(ba.newnode('region',attrs={'position': (0,0,0),'scale': (0.6,2.4,20),'type': 'box','materials': (self._net_wall_material, )})))
def on_team_join(self, team: Team) -> None:
self._update_scoreboard()
def _handle_puck_player_collide(self) -> None:
collision = ba.getcollision()
try:
puck = collision.sourcenode.getdelegate(Puck, True)
player = collision.opposingnode.getdelegate(PlayerSpaz,
True).getplayer(
Player, True)
except ba.NotFoundError:
return
puck.last_players_to_touch[player.team.id] = player
def _kill_puck(self) -> None:
self._puck = None
def _handle_score(self) -> None:
"""A point has been scored."""
assert self._puck is not None
assert self._score_regions is not None
# Our puck might stick around for a second or two
# we don't want it to be able to score again.
if self._puck.scored:
return
region = ba.getcollision().sourcenode
index = 0
for index in range(len(self._score_regions)):
if region == self._score_regions[index].node:
break
for team in self.teams:
if team.id == index:
scoring_team = team
team.score += 1
## Spawn puck on opponent's Area
if team.id == 0: # left side scored
self._puck_spawn_pos= (5, -0.3, 0)
elif team.id == 1: # right side scored
self._puck_spawn_pos= (-5, -0.3, 0)
else: # incase, this dude is oversmart and using 3+ teams...
self._puck_spawn_pos= (0, 0.2, 0)
## Easy pizzy
for player in team.players:
if player.actor:
player.actor.handlemessage(ba.CelebrateMessage(2.0))
# If we've got the player from the scoring team that last
# touched us, give them points.
if (scoring_team.id in self._puck.last_players_to_touch
and self._puck.last_players_to_touch[scoring_team.id]):
self.stats.player_scored(
self._puck.last_players_to_touch[scoring_team.id],
50,
big_message=True)
# End game if we won.
if team.score >= self._score_to_win:
self.end_game()
ba.playsound(self._foghorn_sound)
ba.playsound(self._cheer_sound)
self._puck.scored = True
# Kill the puck (it'll respawn itself shortly).
ba.emitfx(position= ba.getcollision().position, count=int(6.0 + 7.0 * 12), scale=3, spread=0.5, chunk_type='spark')
ba.timer(0.7, self._kill_puck)
ba.cameraflash(duration=7.0)
self._update_scoreboard()
def end_game(self) -> None:
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)
def on_transition_in(self) -> None:
super().on_transition_in()
activity = ba.getactivity()
if self._icy_flooor:
activity.map.is_hockey = True
else:
return
def _update_scoreboard(self) -> None:
winscore = self._score_to_win
for team in self.teams:
self._scoreboard.set_team_value(team, team.score, winscore)
# overriding the default character spawning..
def spawn_player(self, player: Player) -> ba.Actor:
spaz = self.spawn_player_spaz(player)
if self._bombies_:
## We wantthe button to work, justno bombs...
spaz.bomb_count = 0
## Imagine not being able to swipe those colorful buttons ;(
if self._punchie_:
spaz.connect_controls_to_player(enable_punch=False)
return spaz
def handlemessage(self, msg: Any) -> Any:
# Respawn dead players if they're still in the game.
if isinstance(msg, ba.PlayerDiedMessage):
# Augment standard behavior...
super().handlemessage(msg)
self.respawn_player(msg.getplayer(Player))
# Respawn dead pucks.
elif isinstance(msg, PuckDiedMessage):
if not self.has_ended():
ba.timer(2.2, self._spawn_puck)
else:
super().handlemessage(msg)
def _flash_puck_spawn(self) -> None:
## Effect >>>>>> Flashly
ba.emitfx(position= self._puck_spawn_pos, count=int(6.0 + 7.0 * 12), scale=1.7, spread=0.4, chunk_type='spark')
def _spawn_puck(self) -> None:
ba.playsound(self._swipsound)
ba.playsound(self._whistle_sound)
self._flash_puck_spawn()
assert self._puck_spawn_pos is not None
self._puck = Puck(position=self._puck_spawn_pos)

673
dist/ba_root/mods/games/baBasketBomb.py vendored Normal file
View file

@ -0,0 +1,673 @@
# Released under the MIT License. See LICENSE for details.
# ba_meta require api 6
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING
import ba, _ba
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
from bastd.actor.powerupbox import PowerupBoxFactory
from bastd.gameutils import SharedObjects
from bastd.actor import playerspaz as ps
from bastd import maps
if TYPE_CHECKING:
from typing import Any, Sequence, Dict, Type, List, Optional, Union
bsuSpaz = None
def getlanguage(text, sub: str = ''):
lang = _ba.app.lang.language
translate = {
"Name":
{"Spanish": "Baloncesto",
"English": "Basketbomb",
"Portuguese": "Basketbomb"},
"Info":
{"Spanish": "Anota todas las canastas y sé el MVP.",
"English": "Score all the baskets and be the MVP.",
"Portuguese": "Marque cada cesta e seja o MVP."},
"Info-Short":
{"Spanish": f"Anota {sub} canasta(s) para ganar",
"English": f"Score {sub} baskets to win",
"Portuguese": f"Cestas de {sub} pontos para ganhar"},
"S: Powerups":
{"Spanish": "Aparecer Potenciadores",
"English": "Powerups Spawn",
"Portuguese": "Habilitar Potenciadores"},
"S: Velocity":
{"Spanish": "Activar velocidad",
"English": "Enable speed",
"Portuguese": "Ativar velocidade"},
}
languages = ['Spanish','Portuguese','English']
if lang not in languages: lang = 'English'
if text not in translate:
return text
return translate[text][lang]
class BallDiedMessage:
def __init__(self, ball: Ball):
self.ball = ball
class Ball(ba.Actor):
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)):
super().__init__()
shared = SharedObjects.get()
activity = self.getactivity()
velocty = (0.0, 8.0, 0.0)
_scale = 1.2
self._spawn_pos = (position[0], position[1] + 0.5, position[2])
self.last_players_to_touch: Dict[int, Player] = {}
self.scored = False
assert activity is not None
assert isinstance(activity, BasketGame)
pmats = [shared.object_material, activity.ball_material]
self.node = ba.newnode('prop',
delegate=self,
attrs={
'model': activity.ball_model,
'color_texture': activity.ball_tex,
'body': 'sphere',
'reflection': 'soft',
'body_scale': 1.0 * _scale,
'reflection_scale': [1.3],
'shadow_size': 1.0,
'gravity_scale': 0.92,
'density': max(0.4 * _scale, 0.3),
'position': self._spawn_pos,
'velocity': velocty,
'materials': pmats})
self.scale = scale = 0.25 * _scale
ba.animate(self.node, 'model_scale', {0: 0, 0.2: scale*1.3, 0.26: scale})
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
assert self.node
self.node.delete()
activity = self._activity()
if activity and not msg.immediate:
activity.handlemessage(BallDiedMessage(self))
elif isinstance(msg, ba.OutOfBoundsMessage):
assert self.node
self.node.position = self._spawn_pos
self.node.velocity = (0.0, 0.0, 0.0)
elif isinstance(msg, ba.HitMessage):
assert self.node
assert msg.force_direction is not None
self.node.handlemessage(
'impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0],
msg.velocity[1], msg.velocity[2], 1.0 * msg.magnitude,
1.0 * msg.velocity_magnitude, msg.radius, 0,
msg.force_direction[0], msg.force_direction[1],
msg.force_direction[2])
s_player = msg.get_source_player(Player)
if s_player is not None:
activity = self._activity()
if activity:
if s_player in activity.players:
self.last_players_to_touch[s_player.team.id] = s_player
else:
super().handlemessage(msg)
class Player(ba.Player['Team']):
"""Our player type for this game."""
class Team(ba.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.score = 0
class Points:
postes = dict()
postes['pal_0'] = (10.64702320098877, 0.0000000000000000, 0.0000000000000000) #10.736066818237305, 0.3002409040927887, 0.5281256437301636
postes['pal_1'] = (-10.64702320098877, 0.0000000000000000, 0.0000000000000000)
# ba_meta export game
class BasketGame(ba.TeamGameActivity[Player, Team]):
name = getlanguage('Name')
description = getlanguage('Info')
available_settings = [
ba.IntSetting(
'Score to Win',
min_value=1,
default=1,
increment=1,
),
ba.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
('1 Minute', 60),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600),
('20 Minutes', 1200),
],
default=0,
),
ba.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
('Short', 0.5),
('Normal', 1.0),
('Long', 2.0),
('Longer', 4.0),
],
default=1.0,
),
ba.BoolSetting(getlanguage('S: Powerups'), default=True),
ba.BoolSetting(getlanguage('S: Velocity'), default=False),
ba.BoolSetting('Epic Mode', default=False),
]
default_music = ba.MusicType.HOCKEY
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.DualTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ['BasketBall Stadium', 'BasketBall Stadium V2']
def __init__(self, settings: dict):
super().__init__(settings)
shared = SharedObjects.get()
self._scoreboard = Scoreboard()
self._cheer_sound = ba.getsound('cheer')
self._chant_sound = ba.getsound('crowdChant')
self._foghorn_sound = ba.getsound('foghorn')
self._swipsound = ba.getsound('swip')
self._whistle_sound = ba.getsound('refWhistle')
self.ball_model = ba.getmodel('shield')
self.ball_tex = ba.gettexture('fontExtras3')
self._ball_sound = ba.getsound('bunnyJump')
self._powerups = bool(settings[getlanguage('S: Powerups')])
self._speed = bool(settings[getlanguage('S: Velocity')])
self._epic_mode = bool(settings['Epic Mode'])
self.slow_motion = self._epic_mode
self.ball_material = ba.Material()
self.ball_material.add_actions(actions=(('modify_part_collision',
'friction', 0.5)))
self.ball_material.add_actions(conditions=('they_have_material',
shared.pickup_material),
actions=('modify_part_collision',
'collide', True))
self.ball_material.add_actions(
conditions=(
('we_are_younger_than', 100),
'and',
('they_have_material', shared.object_material),
),
actions=('modify_node_collision', 'collide', False),
)
self.ball_material.add_actions(conditions=('they_have_material',
shared.footing_material),
actions=('impact_sound',
self._ball_sound, 0.2, 5))
# Keep track of which player last touched the ball
self.ball_material.add_actions(
conditions=('they_have_material', shared.player_material),
actions=(('call', 'at_connect',
self._handle_ball_player_collide), ))
self._score_region_material = ba.Material()
self._score_region_material.add_actions(
conditions=('they_have_material', self.ball_material),
actions=(('modify_part_collision', 'collide',
True), ('modify_part_collision', 'physical', False),
('call', 'at_connect', self._handle_score)))
self._ball_spawn_pos: Optional[Sequence[float]] = None
self._score_regions: Optional[List[ba.NodeActor]] = None
self._ball: Optional[Ball] = None
self._score_to_win = int(settings['Score to Win'])
self._time_limit = float(settings['Time Limit'])
def get_instance_description(self) -> Union[str, Sequence]:
return getlanguage('Info-Short', sub=self._score_to_win)
def get_instance_description_short(self) -> Union[str, Sequence]:
return getlanguage('Info-Short', sub=self._score_to_win)
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self._time_limit)
if self._powerups:
self.setup_standard_powerup_drops()
self._ball_spawn_pos = self.map.get_flag_position(None)
self._spawn_ball()
defs = self.map.defs
self._score_regions = []
self._score_regions.append(
ba.NodeActor(
ba.newnode('region',
attrs={
'position': defs.boxes['goal1'][0:3],
'scale': defs.boxes['goal1'][6:9],
'type': 'box',
'materials': []
})))
self._score_regions.append(
ba.NodeActor(
ba.newnode('region',
attrs={
'position': defs.boxes['goal2'][0:3],
'scale': defs.boxes['goal2'][6:9],
'type': 'box',
'materials': []
})))
self._update_scoreboard()
ba.playsound(self._chant_sound)
for id, team in enumerate(self.teams):
self.postes(id)
def on_team_join(self, team: Team) -> None:
self._update_scoreboard()
def _handle_ball_player_collide(self) -> None:
collision = ba.getcollision()
try:
ball = collision.sourcenode.getdelegate(Ball, True)
player = collision.opposingnode.getdelegate(PlayerSpaz,
True).getplayer(
Player, True)
except ba.NotFoundError:
return
ball.last_players_to_touch[player.team.id] = player
def _kill_ball(self) -> None:
self._ball = None
def _handle_score(self, team_index: int = None) -> None:
assert self._ball is not None
assert self._score_regions is not None
if self._ball.scored:
return
region = ba.getcollision().sourcenode
index = 0
for index in range(len(self._score_regions)):
if region == self._score_regions[index].node:
break
if team_index is not None:
index = team_index
for team in self.teams:
if team.id == index:
scoring_team = team
team.score += 1
for player in team.players:
if player.actor:
player.actor.handlemessage(ba.CelebrateMessage(2.0))
if (scoring_team.id in self._ball.last_players_to_touch
and self._ball.last_players_to_touch[scoring_team.id]):
self.stats.player_scored(
self._ball.last_players_to_touch[scoring_team.id],
100, big_message=True)
if team.score >= self._score_to_win:
self.end_game()
#ba.playsound(self._foghorn_sound)
ba.playsound(self._cheer_sound)
self._ball.scored = True
# Kill the ball (it'll respawn itself shortly).
ba.timer(1.0, self._kill_ball)
light = ba.newnode('light',
attrs={
'position': ba.getcollision().position,
'height_attenuated': False,
'color': (1, 0, 0)
})
ba.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
ba.timer(1.0, light.delete)
ba.cameraflash(duration=10.0)
self._update_scoreboard()
def end_game(self) -> None:
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)
def _update_scoreboard(self) -> None:
winscore = self._score_to_win
for id, team in enumerate(self.teams):
self._scoreboard.set_team_value(team, team.score, winscore)
#self.postes(id)
def spawn_player(self, player: Player) -> ba.Actor:
if bsuSpaz is None:
spaz = self.spawn_player_spaz(player)
else:
ps.PlayerSpaz = bsuSpaz.BskSpaz
spaz = self.spawn_player_spaz(player)
ps.PlayerSpaz = bsuSpaz.OldPlayerSpaz
if self._speed:
spaz.node.hockey = True
return spaz
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
super().handlemessage(msg)
self.respawn_player(msg.getplayer(Player))
elif isinstance(msg, BallDiedMessage):
if not self.has_ended():
ba.timer(3.0, self._spawn_ball)
else:
super().handlemessage(msg)
def postes(self, team_id: int):
if not hasattr(self._map, 'poste_'+str(team_id)):
setattr(self._map, 'poste_'+str(team_id),
Palos(team=team_id,
position=Points.postes['pal_' +
str(team_id)]).autoretain())
def _flash_ball_spawn(self) -> None:
light = ba.newnode('light',
attrs={
'position': self._ball_spawn_pos,
'height_attenuated': False,
'color': (1, 0, 0)
})
ba.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True)
ba.timer(1.0, light.delete)
def _spawn_ball(self) -> None:
ba.playsound(self._swipsound)
ba.playsound(self._whistle_sound)
self._flash_ball_spawn()
assert self._ball_spawn_pos is not None
self._ball = Ball(position=self._ball_spawn_pos)
class Aro(ba.Actor):
def __init__(self, team: int = 0,
position: Sequence[float] = (0.0, 1.0, 0.0)):
super().__init__()
act = self.getactivity()
shared = SharedObjects.get()
setattr(self, 'team', team)
setattr(self, 'locs', [])
# Material Para; Traspasar Objetos
self.no_collision = ba.Material()
self.no_collision.add_actions(
actions=(('modify_part_collision', 'collide', False)))
self.collision = ba.Material()
self.collision.add_actions(
actions=(('modify_part_collision', 'collide', True)))
# Score
self._score_region_material = ba.Material()
self._score_region_material.add_actions(
conditions=('they_have_material', act.ball_material),
actions=(('modify_part_collision', 'collide',
True), ('modify_part_collision', 'physical', False),
('call', 'at_connect', self._annotation)))
self._spawn_pos = (position[0], position[1], position[2])
self._materials_region0 = [self.collision,
shared.footing_material]
model = None
tex = ba.gettexture('null')
pmats = [self.no_collision]
self.node = ba.newnode('prop',
delegate=self,
attrs={
'model': model,
'color_texture': tex,
'body': 'box',
'reflection': 'soft',
'reflection_scale': [1.5],
'shadow_size': 0.1,
'position': self._spawn_pos,
'materials': pmats})
self.scale = scale = 1.4
ba.animate(self.node, 'model_scale', {0: 0})
pos = (position[0], position[1]+0.6, position[2])
self.regions: List[ba.Node] = [
ba.newnode('region',
attrs={'position': position,
'scale': (0.6, 0.05, 0.6),
'type': 'box',
'materials': self._materials_region0}),
ba.newnode('region',
attrs={'position': pos,
'scale': (0.5, 0.3, 0.9),
'type': 'box',
'materials': [self._score_region_material]})
]
self.regions[0].connectattr('position', self.node, 'position')
#self.regions[0].connectattr('position', self.regions[1], 'position')
locs_count = 9
pos = list(position)
try:
id = 0 if team == 1 else 1
color = act.teams[id].color
except: color = (1,1,1)
while locs_count > 1:
scale = (1.5 * 0.1 * locs_count) + 0.8
self.locs.append(ba.newnode('locator',
owner=self.node,
attrs={'shape': 'circleOutline',
'position': pos,
'color': color,
'opacity': 1.0,
'size': [scale],
'draw_beauty': True,
'additive': False}))
pos[1] -= 0.1
locs_count -= 1
def _annotation(self):
assert len(self.regions) >= 2
ball = self.getactivity()._ball
if ball:
p = self.regions[0].position
ball.node.position = p
ball.node.velocity = (0.0, 0.0, 0.0)
act = self.getactivity()
act._handle_score(self.team)
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
if self.node.exists():
self.node.delete()
else:
super().handlemessage(msg)
class Cuadro(ba.Actor):
def __init__(self, team: int = 0,
position: Sequence[float] = (0.0, 1.0, 0.0)):
super().__init__()
act = self.getactivity()
shared = SharedObjects.get()
setattr(self, 'locs', [])
self.collision = ba.Material()
self.collision.add_actions(
actions=(('modify_part_collision', 'collide', True)))
pos = (position[0], position[1]+0.9, position[2]+1.5)
self.region: ba.Node = ba.newnode('region',
attrs={'position': pos,
'scale': (0.5, 2.7, 2.5),
'type': 'box',
'materials': [self.collision,
shared.footing_material]})
#self.shield = ba.newnode('shield', attrs={'radius': 1.0, 'color': (0,10,0)})
#self.region.connectattr('position', self.shield, 'position')
position = (position[0], position[1], position[2]+0.09)
pos = list(position)
oldpos = list(position)
old_count = 14
count = old_count
count_y = 9
try:
id = 0 if team == 1 else 1
color = act.teams[id].color
except: color = (1,1,1)
while(count_y != 1):
while(count != 1):
pos[2] += 0.19
self.locs.append(
ba.newnode('locator',
owner=self.region,
attrs={'shape': 'circle',
'position': pos,
'size': [0.5],
'color': color,
'opacity': 1.0,
'draw_beauty': True,
'additive': False}))
count -= 1
count = old_count
pos[1] += 0.2
pos[2] = oldpos[2]
count_y -= 1
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
if self.node.exists():
self.node.delete()
else:
super().handlemessage(msg)
class Palos(ba.Actor):
def __init__(self, team: int = 0,
position: Sequence[float] = (0.0, 1.0, 0.0)):
super().__init__()
shared = SharedObjects.get()
activity = self.getactivity()
self._pos = position
self.aro = None
self.cua = None
# Material Para; Traspasar Objetos
self.no_collision = ba.Material()
self.no_collision.add_actions(
actions=(('modify_part_collision', 'collide', False)))
#
self.collision = ba.Material()
self.collision.add_actions(
actions=(('modify_part_collision', 'collide', True)))
# Spawn just above the provided point.
self._spawn_pos = (position[0], position[2]+2.5, position[2])
model = ba.getmodel('flagPole')
tex = ba.gettexture('flagPoleColor')
pmats = [self.no_collision]
self.node = ba.newnode('prop',
delegate=self,
attrs={
'model': model,
'color_texture': tex,
'body': 'puck',
'reflection': 'soft',
'reflection_scale': [2.6],
'shadow_size': 0,
'is_area_of_interest': True,
'position': self._spawn_pos,
'materials': pmats
})
self.scale = scale = 4.0
ba.animate(self.node, 'model_scale', {0: scale})
self.loc = ba.newnode('locator',
owner=self.node,
attrs={'shape': 'circle',
'position': position,
'color': (1,1,0),
'opacity': 1.0,
'draw_beauty': False,
'additive': True})
self._y = _y = 0.30
_x = -0.25 if team == 1 else 0.25
_pos = (position[0]+_x, position[1]-1.5 + _y, position[2])
self.region = ba.newnode('region',
attrs={
'position': _pos,
'scale': (0.4, 8, 0.4),
'type': 'box',
'materials': [self.collision]})
self.region.connectattr('position', self.node, 'position')
_y = self._y
position = self._pos
if team == 0:
pos = (position[0]-0.8, position[1] + 2.0 + _y, position[2])
else: pos = (position[0]+0.8, position[1] + 2.0 + _y, position[2])
if self.aro is None:
self.aro = Aro(team, pos).autoretain()
if self.cua is None:
pos = (position[0], position[1] + 1.8 + _y, position[2]-1.4)
self.cua = Cuadro(team, pos).autoretain()
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
if self.node.exists():
self.node.delete()
else:
super().handlemessage(msg)

322
dist/ba_root/mods/games/crazyBoxes.py vendored Normal file
View file

@ -0,0 +1,322 @@
# ba_meta require api 6
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING, TypeVar
import ba, random, _ba
from math import cos, sin
from bastd.actor.bomb import Bomb, BombFactory, Blast, ExplodeMessage
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
from bastd.gameutils import SharedObjects
if TYPE_CHECKING:
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional, Callable
class DisconnectMessage():
pass
class ConnectMessage():
pass
class Box(ba.Actor):
# should create our own node instead
def __init__(self,
velocity: Sequence[float] = (0.0, 0.0, 0.0),
bomb_type: str = 'normal',
box_type: str = 'small',
bomb_scale: float = 1.0):
super().__init__()
shared = SharedObjects.get()
factory = BombFactory.get()
self.pos: Sequence[float] = ((-11.857367) + round(random.uniform(0, 23), 6),
round(random.uniform(2, 9), 2),
(-4.3599663) + round(random.uniform(0, 8), 6))
self.random = self.force = self.ang = self.x = self.z = self.momentum = 0
self.typee = box_type
self._exploded, self.ground = False, False
self._explode_callbacks: List[Callable[[Bomb, Blast], Any]] = []
materials: Tuple[ba.Material, ...]
materials = (factory.bomb_material, shared.footing_material,
shared.object_material)
if box_type == 'small':
self.data = {
'walk_force': 9.35,
'jump_force': 190,
'walk_cd': 1474,
'jump_cd': 1500,
'light_color': (1, 0, 0.4),
'points': 100,
'texture': ba.gettexture('star'),
'size': 0.9}
elif box_type == 'large':
self.data = {
'walk_force': 13.3905,
'jump_force': 260,
'walk_cd': 900,
'jump_cd': 3000,
'light_color': (0, 0.2, 1.55),
'points': 50,
'texture': ba.gettexture('egg2'),
'size': 1.2}
self.node = ba.newnode('prop',
delegate=self,
attrs={
'position': self.pos,
'velocity': velocity,
'model': ba.getmodel('powerup'),
'light_model': ba.getmodel('powerup'),
'body': 'crate',
'model_scale': self.data.get('size'),
'body_scale': self.data.get('size'),
'density':0.5,
'gravity_scale': 0.5,
'shadow_size': 0.5,
'color_texture': self.data.get('texture'),
'reflection': 'soft',
'reflection_scale': [0.23],
'materials': materials})
self.light = ba.newnode('light',
attrs={
'color': self.data.get('light_color'),
'radius': 0.4
})
self.node.connectattr('position',self.light,'position')
self.move_used = self.highjump_used = self.jump_used = False
ba.animate(self.node, 'model_scale', {0.0:0.0, 0.7:self.data.get('size')})
ba.timer(1000*0.001, self.start_updating)
def start_updating(self):
self.move_timer = ba.Timer(100*0.001, ba.WeakCall(self.update_ai), repeat=True)
def refresh(self, type_: str = 'move'):
if type_ == 'move':
self.move_used = False
elif type_ == 'jump':
self.jump_used = False
elif type_ == 'highjump':
self.highjump_used = False
def move(self):
try:
if self.node.exists() and not self.move_used and self.node.position[1] < 1.0:
self.move_used = True
ba.timer(self.data.get('walk_cd')*0.001, lambda: self.refresh('move'))
self.ang = random.randint(0,360)
self.x = cos(self.ang) * self.data.get('walk_force')
self.z = sin(self.ang) * self.data.get('walk_force')
self.node.velocity = (self.x, 0, self.z)
except: pass
def high_jump(self):
try:
if self.node.exists() and not self.highjump_used:
self.highjump_used = True
ba.timer(10000*0.001, lambda: self.refresh('highjump'))
self.node.handlemessage("impulse", self.node.position[0], self.node.position[1], self.node.position[2],
0.0, 0.0, 0.0,
self.data.get('jump_force')+70,0,0,0,0,1,0)
except: pass
def jump(self):
try:
if self.node.exists() and not self.jump_used:
self.jump_used = True
ba.timer(self.data.get('jump_cd')*0.001, lambda: self.refresh('jump'))
self.node.handlemessage("impulse", self.node.position[0], self.node.position[1], self.node.position[2],
0.0, 0.0, 0.0,
self.data.get('jump_force'),0,0,0,0,1,0)
except: pass
def act_crazy(self):
try:
if self.node.exists():
self.node.velocity = (self.node.velocity[0]+round(random.uniform(-2.0, 2.0),2), random.random()*1.5, self.node.velocity[2]+round(random.uniform(-2.0, 2.0),2))
self.node.extra_acceleration = (self.node.velocity[0]*1.3, self.node.velocity[1]*45, self.node.velocity[2]*1.3)
except: pass
def update_ai(self):
if not self.node.exists():
self.update_ai = None
return
for p in self.activity.players:
if p.actor.node.exists():
if p.actor.node.hold_node == self.node:
self.act_crazy()
else:
self.node.extra_acceleration = (0, 0, 0)
self.random = random.randint(1,4)
if self.random == 1: self.move()
elif self.random == 2: self.jump()
elif self.random == 3 and self.typee == 'large': self.high_jump()
def on_expire(self) -> None:
super().on_expire()
self._explode_callbacks = []
def respawn(self) -> None: pass
def _handle_die(self) -> None:
# self.respawn()
if self.node:
self.light.delete()
self.node.delete()
def _handle_oob(self) -> None:
self.handlemessage(ba.DieMessage())
def add_explode_callback(self, call: Callable[[Bomb, Blast], Any]) -> None:
self._explode_callbacks.append(call)
def explode(self) -> None:
if self._exploded:
return
self._exploded = True
if self.node:
blast = Blast(position=self.node.position,
velocity=self.node.velocity,
blast_radius=2.4,
blast_type='tnt',
hit_type='normal',
hit_subtype='tnt').autoretain()
for callback in self._explode_callbacks:
callback(self, blast)
ba.timer(0.001, ba.WeakCall(self.handlemessage, ba.DieMessage()))
def _add_material(self, material: ba.Material) -> None:
if not self.node:
return
materials = self.node.materials
if material not in materials:
assert isinstance(materials, tuple)
self.node.materials = materials + (material, )
def _handle_hit(self, msg: ba.HitMessage) -> None:
if msg.hit_subtype == 'tnt': return
if not self._exploded and not msg.hit_type == 'punch':
self.update_ai = None
ba.timer(0.1 + random.random() * 0.1,
ba.WeakCall(self.handlemessage, ExplodeMessage()))
killer = msg.get_source_player(ba.Player)
if killer is not None:
assert killer.team is not None
self.activity.stats.player_scored(killer, self.data.get('points'), screenmessage=False, color=(killer.actor.node.color[0]+0.3, killer.actor.node.color[1]+0.3, killer.actor.node.color[2]+0.3))
killer.team.score += self.data.get('points')
ba.playsound(self.activity._dingsound)
self.activity._update_scoreboard()
self.move_timer = None
if msg.srcnode: pass
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ExplodeMessage):
self.explode()
elif isinstance(msg, ba.HitMessage):
self._handle_hit(msg)
elif isinstance(msg, ba.DieMessage):
ba.timer(random.randrange(1500,5020,50)*0.001, lambda: Box(box_type=self.typee).autoretain())
self._handle_die()
elif isinstance(msg, ba.OutOfBoundsMessage):
self._handle_oob()
else:
super().handlemessage(msg)
class Player(ba.Player['Team']):
...
class Team(ba.Team[Player]):
def __init__(self) -> None:
self.score = 0
# ba_meta export game
class CrazyBoxGame(ba.TeamGameActivity[Player, Team]):
"""A game type based on acquiring kills."""
name = 'Crazy Box'
description = 'Blow up the Crazy Boxes!'
announce_player_deaths = True
@classmethod
def get_available_settings(
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
settings = [
ba.IntSetting('Points to win per Player',min_value=50,default=800, increment=50),
ba.IntSetting('Small Box Count',min_value=1,default=1, increment=1),
ba.IntSetting('Large Box Count',min_value=1,default=2, increment=1),
ba.IntChoiceSetting('Time Limit', choices=[('None', 0),('1 Minute', 60),('2 Minutes', 120),('5 Minutes', 300),('10 Minutes', 600),('20 Minutes', 1200)],default=0),
ba.FloatChoiceSetting('Respawn Times',choices=[('Shorter', 0.25),('Short', 0.5),('Normal', 1.0),('Long', 2.0),('Longer', 4.0)], default=1.0),
ba.BoolSetting('Epic Mode', default=False)
]
return settings
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return (issubclass(sessiontype, ba.DualTeamSession)
or issubclass(sessiontype, ba.FreeForAllSession))
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ['Football Stadium']
def __init__(self, settings: dict):
super().__init__(settings)
self.co = int(settings["Small Box Count"])
self.c2 = int(settings["Large Box Count"])
self._scoreboard = Scoreboard()
self._score_to_win: Optional[int] = None
self._dingsound = ba.getsound('dingSmall')
self._epic_mode = bool(settings['Epic Mode'])
self.boxes_to_win = int(settings['Points to win per Player'])
self._time_limit = float(settings['Time Limit'])
self.region: List[ba.NodeActor] = []
self.block_box_mat = ba.Material()
self.block_box_mat.add_actions(conditions=('they_have_material', BombFactory.get().bomb_material),
actions=(('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)))
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
ba.MusicType.FORWARD_MARCH)
def _setup_standard_tnt_drops(self) -> None:
pass
def get_instance_description(self) -> Union[str, Sequence]:
return 'Blow up boxes and score ${ARG1} points to win!', self.boxes_to_win
def on_team_join(self, team: Team) -> None:
if self.has_begun():
self._update_scoreboard()
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self._time_limit)
for i in range(self.co):
Box().autoretain()
for a in range(self.c2):
Box(box_type='large').autoretain()
self.setup_standard_powerup_drops()
b = self.map.defs.boxes['map_bounds']
self.region.append(ba.NodeActor(ba.newnode('region', attrs={'position':(b[0], b[1]+10, b[2]), 'type':'box', 'scale': (b[6], 1.0, b[8]), 'materials': [self.block_box_mat]})))
self._score_to_win = (self.boxes_to_win *
max(1, max(len(t.players) for t in self.teams)))
self._update_scoreboard()
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
super().handlemessage(msg)
player = msg.getplayer(Player)
self.respawn_player(player)
else:
return super().handlemessage(msg)
return None
def _update_scoreboard(self) -> None:
for team in self.teams:
self._scoreboard.set_team_value(team, team.score,
self._score_to_win)
if team.score >= self._score_to_win: ba.timer(500*0.001, self.end_game)
def end_game(self) -> None:
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)

361
dist/ba_root/mods/games/game.py vendored Normal file
View file

@ -0,0 +1,361 @@
"""Quake Game Activity"""
# ba_meta require api 6
from __future__ import annotations
from typing import TYPE_CHECKING
import random
import enum
import ba
from bastd.actor.scoreboard import Scoreboard
from bastd.actor.powerupbox import PowerupBox
from bastd.gameutils import SharedObjects
import quake.rocket
import quake.railgun
if TYPE_CHECKING:
from typing import Optional, List, Any, Type, Union, Sequence
class Player(ba.Player['Team']):
"""Our player"""
class Team(ba.Team[Player]):
"""Our team"""
def __init__(self) -> None:
self.score = 0
class WeaponType(enum.Enum):
"""Type of weapon"""
ROCKET = 0
RAILGUN = 1
class ObstaclesForm(enum.Enum):
"""Obstacle form"""
CUBE = 0
SPHERE = 1
RANDOM = 2
# ba_meta export game
class QuakeGame(ba.TeamGameActivity[Player, Team]):
"""Quake Team Game Activity"""
name = 'Quake'
description = 'Kill a set number of enemies to win.'
available_settings = [
ba.IntSetting(
'Kills to Win Per Player',
default=15,
min_value=1,
increment=1,
),
ba.IntChoiceSetting(
'Time Limit',
choices=[('None', 0), ('1 Minute', 60), ('2 Minutes', 120),
('5 Minutes', 300), ('10 Minutes', 600),
('20 Minutes', 1200)],
default=0,
),
ba.FloatChoiceSetting(
'Respawn Times',
choices=[('At once', 0.0), ('Shorter', 0.25), ('Short', 0.5),
('Normal', 1.0), ('Long', 2.0), ('Longer', 4.0)],
default=1.0,
),
ba.BoolSetting(
'Speed',
default=True,
),
ba.BoolSetting(
'Enable Jump',
default=True,
),
ba.BoolSetting(
'Enable Pickup',
default=True,
),
ba.BoolSetting(
'Enable Bomb',
default=False,
),
ba.BoolSetting(
'Obstacles',
default=True,
),
ba.IntChoiceSetting(
'Obstacles Form',
choices=[('Cube', ObstaclesForm.CUBE.value),
('Sphere', ObstaclesForm.SPHERE.value),
('Random', ObstaclesForm.RANDOM.value)],
default=0,
),
ba.IntChoiceSetting(
'Weapon Type',
choices=[('Rocket', WeaponType.ROCKET.value),
('Railgun', WeaponType.RAILGUN.value)],
default=WeaponType.ROCKET.value,
),
ba.BoolSetting(
'Obstacles Mirror Shots',
default=False,
),
ba.IntSetting(
'Obstacles Count',
default=16,
min_value=0,
increment=2,
),
ba.BoolSetting(
'Random Obstacles Color',
default=True,
),
ba.BoolSetting(
'Epic Mode',
default=False,
),
]
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.MultiTeamSession) or issubclass(
sessiontype, ba.FreeForAllSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
# TODO add more maps
return ['Football Stadium', 'Monkey Face', 'Doom Shroom']
def __init__(self, settings) -> None:
super().__init__(settings)
self._epic_mode = self.settings_raw['Epic Mode']
self._score_to_win = self.settings_raw['Kills to Win Per Player']
self._time_limit = self.settings_raw['Time Limit']
self._obstacles_enabled = self.settings_raw['Obstacles']
self._obstacles_count = self.settings_raw['Obstacles Count']
self._speed_enabled = self.settings_raw['Speed']
self._bomb_enabled = self.settings_raw['Enable Bomb']
self._pickup_enabled = self.settings_raw['Enable Pickup']
self._jump_enabled = self.settings_raw['Enable Jump']
self._weapon_type = WeaponType(self.settings_raw['Weapon Type'])
self.default_music = (ba.MusicType.EPIC
if self._epic_mode else ba.MusicType.GRAND_ROMP)
self.slow_motion = self._epic_mode
self.announce_player_deaths = True
self._scoreboard = Scoreboard()
self._ding_sound = ba.getsound('dingSmall')
self._shield_dropper: Optional[ba.Timer] = None
def get_instance_description(self) -> Union[str, Sequence]:
return 'Kill ${ARG1} enemies.', self._score_to_win
def on_team_join(self, team: Team) -> None:
team.score = 0
if self.has_begun():
self._update_scoreboard()
def on_begin(self) -> None:
ba.TeamGameActivity.on_begin(self)
ba.getactivity().globalsnode.tint = (0.5, 0.7, 1)
self.drop_shield()
self._shield_dropper = ba.Timer(8,
ba.WeakCall(self.drop_shield),
repeat=True)
self.setup_standard_time_limit(self._time_limit)
if self._obstacles_enabled:
count = self._obstacles_count
gamemap = self.map.getname()
for i in range(count): # TODO: tidy up around here
if gamemap == 'Football Stadium':
radius = (random.uniform(-10, 1),
6,
random.uniform(-4.5, 4.5)) \
if i > count / 2 else (
random.uniform(10, 1), 6, random.uniform(-4.5, 4.5))
else:
radius = (random.uniform(-10, 1),
6,
random.uniform(-8, 8)) \
if i > count / 2 else (
random.uniform(10, 1), 6, random.uniform(-8, 8))
Obstacle(
position=radius,
mirror=self.settings_raw['Obstacles Mirror Shots'],
form=self.settings_raw['Obstacles Form']).autoretain()
self._update_scoreboard()
def drop_shield(self) -> None:
"""Drop a shield powerup in random place"""
# FIXME: should use map defs
shield = PowerupBox(poweruptype='shield',
position=(random.uniform(-10, 10), 6,
random.uniform(-5, 5))).autoretain()
ba.playsound(self._ding_sound)
p_light = ba.newnode('light',
owner=shield.node,
attrs={
'position': (0, 0, 0),
'color': (0.3, 0.0, 0.4),
'radius': 0.3,
'intensity': 2,
'volume_intensity_scale': 10.0
})
shield.node.connectattr('position', p_light, 'position')
ba.animate(p_light, 'intensity', {0: 2, 8: 0})
def spawn_player(self, player: Player) -> None:
spaz = self.spawn_player_spaz(player)
if self._weapon_type == WeaponType.ROCKET:
quake.rocket.RocketLauncher().give(spaz)
elif self._weapon_type == WeaponType.RAILGUN:
quake.railgun.Railgun().give(spaz)
spaz.connect_controls_to_player(enable_jump=self._jump_enabled,
enable_pickup=self._pickup_enabled,
enable_bomb=self._bomb_enabled,
enable_fly=False)
spaz.node.hockey = self._speed_enabled
spaz.spaz_light = ba.newnode('light',
owner=spaz.node,
attrs={
'position': (0, 0, 0),
'color': spaz.node.color,
'radius': 0.12,
'intensity': 1,
'volume_intensity_scale': 10.0
})
spaz.node.connectattr('position', spaz.spaz_light, 'position')
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
ba.TeamGameActivity.handlemessage(self, msg)
player = msg.getplayer(Player)
self.respawn_player(player)
killer = msg.getkillerplayer(Player)
if killer is None:
return
# handle team-kills
if killer.team is player.team:
# in free-for-all, killing yourself loses you a point
if isinstance(self.session, ba.FreeForAllSession):
new_score = player.team.score - 1
new_score = max(0, new_score)
player.team.score = new_score
# in teams-mode it gives a point to the other team
else:
ba.playsound(self._ding_sound)
for team in self.teams:
if team is not killer.team:
team.score += 1
# killing someone on another team nets a kill
else:
killer.team.score += 1
ba.playsound(self._ding_sound)
# in FFA show our score since its hard to find on
# the scoreboard
assert killer.actor is not None
# noinspection PyUnresolvedReferences
killer.actor.set_score_text(str(killer.team.score) + '/' +
str(self._score_to_win),
color=killer.team.color,
flash=True)
self._update_scoreboard()
# if someone has won, set a timer to end shortly
# (allows the dust to clear and draws to occur if
# deaths are close enough)
if any(team.score >= self._score_to_win for team in self.teams):
ba.timer(0.5, self.end_game)
else:
ba.TeamGameActivity.handlemessage(self, msg)
def _update_scoreboard(self) -> None:
for team in self.teams:
self._scoreboard.set_team_value(team, team.score,
self._score_to_win)
def end_game(self) -> None:
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)
class Obstacle(ba.Actor):
"""Scene object"""
def __init__(self,
position,
form=ObstaclesForm.CUBE,
mirror=False) -> None:
ba.Actor.__init__(self)
if form == ObstaclesForm.CUBE:
model = 'tnt'
body = 'crate'
elif form == ObstaclesForm.SPHERE:
model = 'bomb'
body = 'sphere'
else: # ObstaclesForm.RANDOM:
model = random.choice(['tnt', 'bomb'])
body = 'sphere' if model == 'bomb' else 'crate'
self.node = ba.newnode(
'prop',
delegate=self,
attrs={
'position':
position,
'model':
ba.getmodel(model),
'body':
body,
'body_scale':
1.3,
'model_scale':
1.3,
'reflection':
'powerup',
'reflection_scale': [0.7],
'color_texture':
ba.gettexture('bunnyColor'),
'materials': [SharedObjects.get().footing_material]
if mirror else [
SharedObjects.get().object_material,
SharedObjects.get().footing_material
]
})
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
if self.node:
self.node.delete()
elif isinstance(msg, ba.OutOfBoundsMessage):
if self.node:
self.handlemessage(ba.DieMessage())
elif isinstance(msg, ba.HitMessage):
self.node.handlemessage('impulse', msg.pos[0], msg.pos[1],
msg.pos[2], msg.velocity[0],
msg.velocity[1], msg.velocity[2],
msg.magnitude, msg.velocity_magnitude,
msg.radius, 0, msg.velocity[0],
msg.velocity[1], msg.velocity[2])

117
dist/ba_root/mods/games/ms_BombWar.py vendored Normal file
View file

@ -0,0 +1,117 @@
# ba_meta require api 6
"""
BombWar Mini game
by : Mr.Smoothy
discord : mr.smoothy#5824
download more , contribute : https://discord.gg/ucyaesh
"""
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
from bastd.game.deathmatch import DeathMatchGame, Player, Team
from bastd.actor.bomb import Bomb
import bastd
if TYPE_CHECKING:
from typing import Sequence
from bastd.gameutils import SharedObjects
# ba_meta export game
class BombWar(DeathMatchGame):
name = 'Bomb War'
def __init__(self, settings: dict):
super().__init__(settings)
shared = SharedObjects.get()
self._wall_material=ba.Material()
self._fake_wall_material=ba.Material()
self._wall_material.add_actions(
actions=(
('modify_part_collision', 'friction', 100000),
))
self._wall_material.add_actions(
conditions=('they_have_material', shared.pickup_material),
actions=(
('modify_part_collision', 'collide', False),
))
self._wall_material.add_actions(
conditions=(('we_are_younger_than', 100),
'and',
('they_have_material',shared.object_material)),
actions=(
('modify_part_collision', 'collide', False),
))
self._wall_material.add_actions(
conditions=('they_have_material',shared.footing_material),
actions=(
('modify_part_collision', 'friction', 9999.5),
))
self._wall_material.add_actions(
conditions=('they_have_material', bastd.actor.bomb.BombFactory.get().blast_material),
actions=(
('modify_part_collision', 'collide', False),
('modify_part_collision', 'physical', False)
))
self._fake_wall_material.add_actions(
conditions=('they_have_material', shared.player_material),
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)
))
self.blocks=[]
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self._time_limit)
factory = bastd.actor.bomb.BombFactory.get()
shared = SharedObjects.get()
for i in [-5.5,-4.5,-3.5,-2.5,-1.5,-0.5,0.5,1.5,2.5]:
self.blocks.append(ba.newnode(
'prop',
delegate=self,
attrs={
'body': 'puck',
'position': (-0.1,3,i),
'model': ba.getmodel('tnt'),
# 'light_model': factory.tnt_model,
'shadow_size': 0.5,
'gravity_scale':7.5,
'color_texture': ba.gettexture('puckColor'),
'reflection': 'soft',
'reflection_scale': [1.0],
'materials': (shared.object_material,self._wall_material,)
}) )
for i in [-5.5,-4.5,-3.5,-2.5,-1.5,-0.5,0.5,1.5,2.3]:
self.blocks.append(ba.newnode(
'prop',
delegate=self,
attrs={
'body': 'puck',
'position': (-0.1,5,i),
'model': ba.getmodel('tnt'),
# 'light_model': factory.tnt_model,
'shadow_size': 0.5,
'gravity_scale':7.5,
'color_texture': ba.gettexture('puckColor'),
'reflection': 'soft',
'reflection_scale': [1.0],
'materials': (shared.object_material,self._wall_material,)
}) )
self.blocks.append(ba.NodeActor(ba.newnode('region',attrs={'position': (0,3,-6),'scale': (2,5,20),'type': 'box','materials': (self._fake_wall_material, )})))
# Base kills needed to win on the size of the largest team.
self._score_to_win = (self._kills_to_win_per_player *
max(1, max(len(t.players) for t in self.teams)))
self._update_scoreboard()

BIN
dist/ba_root/mods/games/soccer.so vendored Normal file

Binary file not shown.

88
dist/ba_root/mods/maps/BasketBallMap.py vendored Normal file
View file

@ -0,0 +1,88 @@
import ba
from bastd.gameutils import SharedObjects
from bastd.actor import playerspaz as ps
from bastd import maps
if TYPE_CHECKING:
from typing import Any, Sequence, Dict, Type, List, Optional, Union
class BasketMap(maps.FootballStadium):
name = 'BasketBall Stadium'
@classmethod
def get_play_types(cls) -> List[str]:
"""Return valid play types for this map."""
return []
def __init__(self) -> None:
super().__init__()
gnode = ba.getactivity().globalsnode
gnode.tint = [(0.806, 0.8, 1.0476), (1.3, 1.2, 1.0)][0]
gnode.ambient_color = (1.3, 1.2, 1.0)
gnode.vignette_outer = (0.57, 0.57, 0.57)
gnode.vignette_inner = (0.9, 0.9, 0.9)
gnode.vr_camera_offset = (0, -0.8, -1.1)
gnode.vr_near_clip = 0.5
class BasketMapV2(maps.HockeyStadium):
name = 'BasketBall Stadium V2'
def __init__(self) -> None:
super().__init__()
shared = SharedObjects.get()
self.node.materials = [shared.footing_material]
self.node.collide_model = ba.getcollidemodel('footballStadiumCollide')
self.node.model = None
self.stands.model = None
self.floor.reflection = 'soft'
self.floor.reflection_scale = [1.6]
self.floor.color = (1.1, 0.05, 0.8)
self.background = ba.newnode('terrain',
attrs={'model': ba.getmodel('thePadBG'),
'lighting': False,
'background': True,
'color': (1.0, 0.2, 1.0),
'color_texture': ba.gettexture('menuBG')})
gnode = ba.getactivity().globalsnode
gnode.floor_reflection = True
gnode.debris_friction = 0.3
gnode.debris_kill_height = -0.3
gnode.tint = [(1.2, 1.3, 1.33), (0.7, 0.9, 1.0)][1]
gnode.ambient_color = (1.15, 1.25, 1.6)
gnode.vignette_outer = (0.66, 0.67, 0.73)
gnode.vignette_inner = (0.93, 0.93, 0.95)
gnode.vr_camera_offset = (0, -0.8, -1.1)
gnode.vr_near_clip = 0.5
self.is_hockey = False
##################
self.collision = ba.Material()
self.collision.add_actions(
actions=(('modify_part_collision', 'collide', True)))
self.regions: List[ba.Node] = [
ba.newnode('region',
attrs={'position': (12.676897048950195, 0.2997918128967285, 5.583303928375244),
'scale': (1.01, 12, 28),
'type': 'box',
'materials': [self.collision]}),
ba.newnode('region',
attrs={'position': (11.871315956115723, 0.29975247383117676, 5.711406707763672),
'scale': (50, 12, 0.9),
'type': 'box',
'materials': [self.collision]}),
ba.newnode('region',
attrs={'position': (-12.776557922363281, 0.30036890506744385, 4.96237850189209),
'scale': (1.01, 12, 28),
'type': 'box',
'materials': [self.collision]}),
]
ba._map.register_map(BasketMap)
ba._map.register_map(BasketMapV2)

BIN
dist/ba_root/mods/maps/BridgitMash.so vendored Normal file

Binary file not shown.

Binary file not shown.

56
dist/ba_root/mods/maps/MemoryGame.py vendored Normal file
View file

@ -0,0 +1,56 @@
import ba
from bastd.gameutils import SharedObjects
if TYPE_CHECKING:
from typing import Any, Sequence, Optional, List, Dict, Type, Type , Union, Any, Literal
class MGdefs():
points = {}
boxes = {}
points['flag_default'] = (0.17358, 3.75764, 1.99124)
boxes['area_of_interest_bounds'] = (0.3544110667, 4.493562578, -2.518391331) + (0.0, 0.0, 0.0) + (16.64754831, 8.06138989, 18.5029888)
boxes['map_bounds'] = (0.2608783669, 4.899663734, -3.543675157) + (0.0, 0.0, 0.0) + (29.23565494, 14.19991443, 29.92689344)
class MGmap(ba.Map):
defs = MGdefs()
name = 'Sky Tiles'
@classmethod
def get_play_types(cls) -> List[str]:
"""Return valid play types for this map."""
return []
@classmethod
def get_preview_texture_name(cls) -> str:
return 'achievementOffYouGo'
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'bgtex': ba.gettexture('menuBG'),
'bgmodel': ba.getmodel('thePadBG')
}
return data
def __init__(self) -> None:
super().__init__()
shared = SharedObjects.get()
self.node = ba.newnode(
'terrain',
attrs={
'model': self.preloaddata['bgmodel'],
'lighting': False,
'background': True,
'color_texture': self.preloaddata['bgtex']
})
gnode = ba.getactivity().globalsnode
gnode.tint = (1.3, 1.2, 1.0)
gnode.ambient_color = (1.3, 1.2, 1.0)
gnode.vignette_outer = (0.57, 0.57, 0.57)
gnode.vignette_inner = (0.9, 0.9, 0.9)
gnode.vr_camera_offset = (0, -0.8, -1.1)
gnode.vr_near_clip = 0.5
ba._map.register_map(MGmap)

307
dist/ba_root/mods/maps/VolleBallMap.py vendored Normal file
View file

@ -0,0 +1,307 @@
import ba,_ba
from bastd.gameutils import SharedObjects
if TYPE_CHECKING:
from typing import Any, Sequence, Optional, List, Dict, Type, Type , Union, Any, Literal
a=0.0
class Pointzz:
points, boxes = {}, {}
points['ffa_spawn1'] = (-0.08016, 0.02275, -4.37367) + (8.89506, 0.05, 0.44435)
points['ffa_spawn2'] = (-0.08016, 0.02275, 4.07629) + (8.89506, 0.05, 0.44435)
points['flag1'] = (-10.72073, 0.06537, 0.14648)
points['flag2'] = (10.7587, 0.04779, 0.14648)
points['flag_default'] = (-0.10014, 0.0418, 0.10956)
points['powerup_spawn1'] = (500000000.41468, 50000.9515, -500000.03791)
points['powerup_spawn2'] = (-500000.5554, 500000.9515, -500000.03791)
points['powerup_spawn3'] = (500000.41468, 50000.9515, 5000.14822)
points['powerup_spawn4'] = (-50000.73727, 50000.9515, 500.14822)
points['spawn1'] = (-8.03866, 0.02275, 0.0) + (0.5, 0.05, 4.0)
points['spawn2'] = (8.82311, 0.01092, 0.0) + (0.5, 0.05, 4.0)
boxes['area_of_interest_bounds'] = (0.0, 1.18575, 0.43262) + (0, 0, 0) + (29.81803, 11.57249, 18.89134)
boxes['tnt1'] = (-0.10387, 0.41333, 0.42947) + (0, 0, 0) + (22.48296, 1.29024, 8.99025)
boxes['goal1'] = (10,0.001,8)
boxes['goal2'] = (10,0.001,8)
boxes['map_bounds'] = (0.0, 1.185751251, 0.4326226188) + (0.0, 0.0, 0.0) + (
42.09506485, 22.81173179, 29.76723155)
class PointzzforH:
points, boxes = {}, {}
boxes['area_of_interest_bounds'] = (0.0, 0.7956858119, 0.0) + (
0.0, 0.0, 0.0) + (30.80223883, 0.5961646365, 13.88431707)
points['ffa_spawn1'] = (-0.001925625146, 0.02305323209,
-3.81971842) + (7.828121539, 1.0, 0.1588021252)
points['ffa_spawn2'] = (-0.001925625146, 0.02305323209,
3.560115735) + (7.828121539, 1.0, 0.05859841271)
points['flag1'] = (-11.21689747, 0.09527878981, -0.07659307272)
points['flag2'] = (11.08204909, 0.04119542459, -0.07659307272)
points['flag_default'] = (-0.01690735171, 0.06139940044, -0.07659307272)
boxes['goal1'] = (10,0.001,8)
boxes['goal2'] = (10,0.001,8)
boxes['map_bounds'] = (0.0, 0.7956858119, -0.4689020853) + (0.0, 0.0, 0.0) + (
35.16182389, 12.18696164, 21.52869693)
points['powerup_spawn1'] = (-3.654355317, 1.080990833, -4.765886164)
points['powerup_spawn2'] = (-3.654355317, 1.080990833, 4.599802158)
points['powerup_spawn3'] = (2.881071011, 1.080990833, -4.765886164)
points['powerup_spawn4'] = (2.881071011, 1.080990833, 4.599802158)
points['spawn1'] = (-6.835352227, 0.02305323209, 0.0) + (1.0, 1.0, 3.0)
points['spawn2'] = (6.857415055, 0.03938567998, 0.0) + (1.0, 1.0, 3.0)
points['tnt1'] = (-0.05791962398, 1.080990833, -4.765886164)
class VolleyBallMap(ba.Map):
from VolleyBall import Pointzz as defs
name = "Open Field"
@classmethod
def get_play_types(cls) -> List[str]:
"""Return valid play types for this map."""
return []
@classmethod
def get_preview_texture_name(cls) -> str:
return 'footballStadiumPreview'
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'model': ba.getmodel('footballStadium'),
'vr_fill_model': ba.getmodel('footballStadiumVRFill'),
'collide_model': ba.getcollidemodel('footballStadiumCollide'),
'tex': ba.gettexture('footballStadium')
}
return data
def __init__(self):
super().__init__()
shared = SharedObjects.get()
## Hey Quasi thx for looping these xD ##
x = -5
while x<5:
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(0,0,x),
'color':(1,1,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(0,.25,x),
'color':(1,1,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(0,.5,x),
'color':(1,1,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(0,.75,x),
'color':(1,1,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(0,1,x),
'color':(1,1,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
x = x + 0.5
y = -1
while y>-11:
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(y,0.01,4),
'color':(0,0,1),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(y,0.01,-4),
'color':(0,0,1),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(-y,0.01,4),
'color':(1,0,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(-y,0.01,-4),
'color':(1,0,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
y-=1
z = 0
while z<5:
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(11,0.01,z),
'color':(1,0,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(11,0.01,-z),
'color':(1,0,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(-11,0.01,z),
'color':(0,0,1),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(-11,0.01,-z),
'color':(0,0,1),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
z+=1
self.node = ba.newnode(
'terrain',
delegate=self,
attrs={
'model': self.preloaddata['model'],
'collide_model': self.preloaddata['collide_model'],
'color_texture': self.preloaddata['tex'],
'materials': [shared.footing_material]
})
ba.newnode('terrain',
attrs={
'model': self.preloaddata['vr_fill_model'],
'lighting': False,
'vr_only': True,
'background': True,
'color_texture': self.preloaddata['tex']
})
gnode = ba.getactivity().globalsnode
gnode.tint = (1.3, 1.2, 1.0)
gnode.ambient_color = (1.3, 1.2, 1.0)
gnode.vignette_outer = (0.57, 0.57, 0.57)
gnode.vignette_inner = (0.9, 0.9, 0.9)
gnode.vr_camera_offset = (0, -0.8, -1.1)
gnode.vr_near_clip = 0.5
def is_point_near_edge(self,
point: ba.Vec3,
running: bool = False) -> bool:
box_position = self.defs.boxes['edge_box'][0:3]
box_scale = self.defs.boxes['edge_box'][6:9]
xpos = (point.x - box_position[0]) / box_scale[0]
zpos = (point.z - box_position[2]) / box_scale[2]
return xpos < -0.5 or xpos > 0.5 or zpos < -0.5 or zpos > 0.5
class VolleyBallMapH(ba.Map):
"""Stadium map used for ice hockey games."""
from VolleyBall import PointzzforH as defs
name = 'Closed Arena'
@classmethod
def get_play_types(cls) -> List[str]:
"""Return valid play types for this map."""
return []
@classmethod
def get_preview_texture_name(cls) -> str:
return 'hockeyStadiumPreview'
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'models': (ba.getmodel('hockeyStadiumOuter'),
ba.getmodel('hockeyStadiumInner')),
'vr_fill_model': ba.getmodel('footballStadiumVRFill'),
'collide_model': ba.getcollidemodel('hockeyStadiumCollide'),
'tex': ba.gettexture('hockeyStadium'),
}
mat = ba.Material()
mat.add_actions(actions=('modify_part_collision', 'friction', 0.01))
data['ice_material'] = mat
return data
def __init__(self) -> None:
super().__init__()
shared = SharedObjects.get()
## Hey Quasi thx for looping these xD ##
x = -5
while x<5:
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(0,0,x),
'color':(1,1,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(0,.25,x),
'color':(1,1,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(0,.5,x),
'color':(1,1,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(0,.75,x),
'color':(1,1,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(0,1,x),
'color':(1,1,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
x = x + 0.5
y = -1
while y>-11:
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(y,0.01,4),
'color':(0,0,1),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(y,0.01,-4),
'color':(0,0,1),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(-y,0.01,4),
'color':(1,0,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(-y,0.01,-4),
'color':(1,0,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
y-=1
z = 0
while z<5:
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(11,0.01,z),
'color':(1,0,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(11,0.01,-z),
'color':(1,0,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(-11,0.01,z),
'color':(0,0,1),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(-11,0.01,-z),
'color':(0,0,1),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
z+=1
self.node = ba.newnode('terrain',
delegate=self,
attrs={
'model':
None,
'collide_model':
ba.getcollidemodel('footballStadiumCollide'), ## we dont want Goalposts...
'color_texture':
self.preloaddata['tex'],
'materials': [
shared.footing_material]
})
ba.newnode('terrain',
attrs={
'model': self.preloaddata['vr_fill_model'],
'vr_only': True,
'lighting': False,
'background': True,
})
mats = [shared.footing_material]
self.floor = ba.newnode('terrain',
attrs={
'model': self.preloaddata['models'][1],
'color_texture': self.preloaddata['tex'],
'opacity': 0.92,
'opacity_in_low_or_medium_quality': 1.0,
'materials': mats,
'color': (0.4,0.9,0)
})
self.background = ba.newnode(
'terrain',
attrs={
'model': ba.getmodel('natureBackground'),
'lighting': False,
'background': True,
'color': (0.5,0.30,0.4)
})
gnode = ba.getactivity().globalsnode
gnode.floor_reflection = True
gnode.debris_friction = 0.3
gnode.debris_kill_height = -0.3
gnode.tint = (1.2, 1.3, 1.33)
gnode.ambient_color = (1.15, 1.25, 1.6)
gnode.vignette_outer = (0.66, 0.67, 0.73)
gnode.vignette_inner = (0.93, 0.93, 0.95)
gnode.vr_camera_offset = (0, -0.8, -1.1)
gnode.vr_near_clip = 0.5
#self.is_hockey = True
## Plugin only for our dirty map UwU ##
ba._map.register_map(VolleyBallMap)
ba._map.register_map(VolleyBallMapH)

98
dist/ba_root/mods/maps/WoodenFloor.py vendored Normal file
View file

@ -0,0 +1,98 @@
from __future__ import annotations
from typing import TYPE_CHECKING
import ba,_ba
from bastd.gameutils import SharedObjects
from bastd.actor.playerspaz import PlayerSpaz
if TYPE_CHECKING:
from typing import Any, List, Dict
class WoodenFloor(ba.Map):
"""Stadium map for football games."""
from bastd.mapdata import football_stadium as defs
defs.points['spawn1'] = (-12.03866341, 0.02275111462, 0.0) + (0.5, 1.0, 4.0)
defs.points['spawn2'] = (12.823107149, 0.01092306765, 0.0) + (0.5, 1.0, 4.0)
name = 'Wooden Floor'
@classmethod
def get_play_types(cls) -> list[str]:
"""Return valid play types for this map."""
return ['melee', 'football', 'team_flag', 'keep_away']
@classmethod
def get_preview_texture_name(cls) -> str:
return 'footballStadiumPreview'
@classmethod
def on_preload(cls) -> Any:
data: dict[str, Any] = {
'model_bg': ba.getmodel('doomShroomBG'),
'bg_vr_fill_model': ba.getmodel('natureBackgroundVRFill'),
'collide_model': ba.getcollidemodel('bridgitLevelCollide'),
'tex': ba.gettexture('bridgitLevelColor'),
'model_bg_tex': ba.gettexture('doomShroomBGColor'),
'collide_bg': ba.getcollidemodel('natureBackgroundCollide'),
'railing_collide_model':
(ba.getcollidemodel('bridgitLevelRailingCollide')),
'bg_material': ba.Material()
}
data['bg_material'].add_actions(actions=('modify_part_collision',
'friction', 10.0))
return data
def __init__(self) -> None:
super().__init__()
shared = SharedObjects.get()
self.background = ba.newnode(
'terrain',
attrs={
'model': self.preloaddata['model_bg'],
'lighting': False,
'background': True,
'color_texture': self.preloaddata['model_bg_tex']
})
ba.newnode('terrain',
attrs={
'model': self.preloaddata['bg_vr_fill_model'],
'lighting': False,
'vr_only': True,
'background': True,
'color_texture': self.preloaddata['model_bg_tex']
})
gnode = ba.getactivity().globalsnode
gnode.tint = (1.3, 1.2, 1.0)
gnode.ambient_color = (1.3, 1.2, 1.0)
gnode.vignette_outer = (0.57, 0.57, 0.57)
gnode.vignette_inner = (0.9, 0.9, 0.9)
gnode.vr_camera_offset = (0, -0.8, -1.1)
gnode.vr_near_clip = 0.5
# self.map_extend()
def is_point_near_edge(self,
point: ba.Vec3,
running: bool = False) -> bool:
box_position = self.defs.boxes['edge_box'][0:3]
box_scale = self.defs.boxes['edge_box'][6:9]
xpos = (point.x - box_position[0]) / box_scale[0]
zpos = (point.z - box_position[2]) / box_scale[2]
return xpos < -0.5 or xpos > 0.5 or zpos < -0.5 or zpos > 0.5
def _handle_player_collide(self):
try:
player = ba.getcollision().opposingnode.getdelegate(
PlayerSpaz, True)
except ba.NotFoundError:
return
if player.is_alive():
player.shatter(True)
ba._map.register_map(WoodenFloor)

334
dist/ba_root/mods/maps/baMaps_v1.py vendored Normal file
View file

@ -0,0 +1,334 @@
# ba_meta require api 6
# Plugin SEBASTIAN2059 - Zacker Tz
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# - Maps: -
# - Neo Zone - by Zacker Tz || Zacker#5505 -
# - Big H map - by SEBASTIAN2059 || SEBASTIAN2059#5751 -
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
from __future__ import annotations
from typing import TYPE_CHECKING
from bastd.maps import *
import ba
import _ba
import base64
from ba import _map
import random
if TYPE_CHECKING:
from typing import Any, List, Dict
#Map by Zacker Tz
class neo_defs():
boxes = {}
points = {}
boxes['area_of_interest_bounds'] = (0, 4, 0) + (0, 0, 0) + (50, 10, 20)
boxes['edge_box'] = (0, 4, 0) + (0.0, 0.0, 0.0) + (40, 2, 10)
boxes['map_bounds'] = (0, 4, 0) + (0, 0, 0) + (28, 10, 28)
points['ffa_spawn1'] = (-10,3.17,0) + (1.0,0.1,1.0)
points['ffa_spawn2'] = (10,3.17,0) + (1.0,0.1,1.0)
points['ffa_spawn3'] = (-5.25,3.17,-1.75) + (0.5,0.1,0.5)
points['ffa_Spawn4'] = (5.25,3.17,-1.75) + (0.5,0.1,0.5)
points['spawn1'] = (-11,3.17,0) + (1.0,0.1,1.0)
points['spawn2'] = (11,3.17,0) + (1.0,0.1,1.0)
points['flag1'] = (-12.0,3.3,0) + (2.0,0.1,2.0)
points['flag2'] = (12.0,3.3,0) + (2.0,0.1,2.0)
points['flag_default'] = (0,3.3,1.75)
points['powerup_spawn1'] = (-11,4.0,-1.75)
points['powerup_spawn2'] = (-11,4.0,1.75)
points['powerup_spawn3'] = (-1.75,4.0,0)
points['powerup_spawn4'] = (1.75,4.0,0.0)
points['powerup_spawn5'] = (11,4.0,-1.75)
points['powerup_spawn6'] = (11,4.0,1.75)
class NeoZone(ba.Map):
"""Agent john's former workplace"""
defs = neo_defs()
name = 'Neo Zone'
@classmethod
def get_play_types(cls) -> List[str]:
"""Return valid play types for this map."""
return ['melee','king_of_the_hill','keep_away','team_flag']
@classmethod
def get_preview_texture_name(cls) -> str:
return 'rgbStripes'
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'model': ba.getmodel('landMine'),
'tex': ba.gettexture('landMine'),
'bgtex': ba.gettexture('black'),
'bgmodel': ba.getmodel('thePadBG'),
}
return data
def __init__(self) -> None:
super().__init__()
shared = SharedObjects.get()
self._collide_with_player=ba.Material()
self._collide_with_player.add_actions(conditions=('we_are_older_than', 1), actions=(('modify_part_collision', 'collide', True)))
self.dont_collide=ba.Material()
self.dont_collide.add_actions(conditions=('they_are_different_node_than_us', ),actions=(('modify_part_collision', 'collide', False)))
self._map_model = ba.getmodel('image1x1')
self._map_model2 = ba.getmodel('tnt')
self._map_tex = ba.gettexture('powerupIceBombs')
self._map_tex1 = ba.gettexture('ouyaUButton')
self.background = ba.newnode('terrain',
attrs={
'model': self.preloaddata['bgmodel'],
'lighting': False,
'background': True,
'color_texture': self.preloaddata['bgtex']
})
locations = [(7.0,0.0,0),(5.25,0.0,0),(5.25,0.0,-1.75),
(3.5,0.0,-1.75),(1.75,0.0,-1.75),(1.75,0.0,0),
(1.75,0.0,1.75),
(0,0.0,1.75),
(-7.0,0.0,0),(-5.25,0.0,0),(-5.25,3.17,-1.75),
(-3.5,0.0,-1.75),(-1.75,0.0,-1.75),(-1.75,0.0,0),
(-1.75,0.0,1.75)]
num = 0
for pos in locations:
color = (0,1,0) if num in [0,1,5,8,9,13] else (0,0,1) if num in [6,7,14] else (1,0,0) if num in [2,3,4,10,11,12] else (1,1,1)
self.decor = ba.newnode('prop',
attrs={'body': 'puck',
'position': (pos[0],3.17,pos[2]),
'model': self._map_model,
'model_scale': 1.7,
'body_scale': 0.1,
'shadow_size': 0.0,
'gravity_scale':0.0,
'color_texture': self._map_tex1,
'reflection': 'soft',
'reflection_scale': [0.5],
'is_area_of_interest': True,
'materials': [self.dont_collide]})
self.region = ba.newnode('region',attrs={
'position': (pos[0],2.3,pos[2]),
'scale': (1.9,1.9,1.9),
'type': 'box',
'materials': (self._collide_with_player, shared.footing_material)})
self.zone = ba.newnode('locator',
attrs={'shape':'box',
'position':(pos[0],2.3,pos[2]),
'color':color,
'opacity':1,'draw_beauty':True,'additive':False,'size':[1.75,1.75,1.75]})
num += 1
#Sides
side_locations = [(-10.5,2.3,0),(10.5,2.3,0)]
for pos in side_locations:
self.big_region = ba.newnode('region',attrs={
'position': pos,
'scale': (5.7,1.9,5.7),
'type': 'box',
'materials': (self._collide_with_player, shared.footing_material)})
self.big_zone = ba.newnode('locator',
attrs={'shape':'box',
'position':pos,
'color':(0,1,1.5),
'opacity':1,'draw_beauty':True,'additive':False,'size':[5.25,1.75,5.25]})
exec(base64.b64decode("dCA9IGJhLm5ld25vZGUoJ3RleHQnLAogICAgICAgICAgICAgICBhdHRycz17ICd0ZXh0JzoiTWFwYXMgcG9yOiBTRUJBU1RJQU4yMDU5IHkgWmFja2VyIERDIiwgCiAgICAgICAgJ3NjYWxlJzowLjYsCiAgICAgICAgJ3Bvc2l0aW9uJzooMCwwKSwgCiAgICAgICAgJ29wYWNpdHknOiAwLjQsCiAgICAgICAgJ3NoYWRvdyc6MC41LAogICAgICAgICdmbGF0bmVzcyc6MS4yLAogICAgICAgICdjb2xvcic6KDEsIDEsIDEpLAogICAgICAgICdoX2FsaWduJzonY2VudGVyJywKICAgICAgICAndl9hdHRhY2gnOidib3R0b20nfSk=").decode('UTF-8')) #bubalu
gnode = ba.getactivity().globalsnode
gnode.tint = (1.1, 1.05, 1.17)
gnode.happy_thoughts_mode = False
gnode.ambient_color = (1.2, 1.17, 1.1)
gnode.vignette_outer = (0.9, 0.9, 0.96)
gnode.vignette_inner = (0.95, 0.95, 0.93)
#Map by Sebastian2059
class c_defs():
boxes = {}
points = {}
boxes['area_of_interest_bounds'] = (0, 4, 0) + (0, 0, 0) + (50, 10, 20)
boxes['edge_box'] = (0, 4, 0) + (0.0, 0.0, 0.0) + (40, 2, 10)
boxes['map_bounds'] = (0, 4, 0) + (0, 0, 0) + (28, 10, 28)
points['ffa_spawn1'] = (-9,0.5,-3) + (1.0,0.1,5.0)
points['ffa_spawn2'] = (9,0.5,-3) + (1.0,0.1,5.0)
points['ffa_spawn3'] = (-6,0.5,-6.0) + (2.0,0.1,1.0)
points['ffa_Spawn4'] = (6,0.5,0.0) + (2.0,0.1,1.0)
points['ffa_spawn5'] = (6,0.5,-6.0) + (2.0,0.1,1.0)
points['ffa_Spawn6'] = (-6,0.5,0.0) + (2.0,0.1,1.0)
points['spawn1'] = (-9,0.5,-3) + (1.0,0.1,1.0)
points['spawn2'] = (9,0.5,-3) + (1.0,0.1,1.0)
points['flag1'] = (-10.0,0.8,-3) + (2.0,0.1,2.0)
points['flag2'] = (10.0,0.8,-3) + (2.0,0.1,2.0)
points['flag_default'] = (0,0.8,-3.0)
points['powerup_spawn1'] = (-9,1.0,-8)
points['powerup_spawn2'] = (-9,1.0,3)
points['powerup_spawn3'] = (-1.5,1.0,-8.25)
points['powerup_spawn4'] = (1.5,1.0,-8.25)
points['powerup_spawn5'] = (-1.5,1.0,2.25)
points['powerup_spawn6'] = (1.5,1.0,2.25)
points['powerup_spawn7'] = (9,1.0,-8)
points['powerup_spawn8'] = (9,1.0,3)
points['race_mine1'] = (-1.5, 0.7, -0.7)
points['race_mine2'] = (-1.5, 0.7, 0.7)
points['race_mine3'] = (-4.5, 0.7, 0.0)
points['race_mine4'] = (4.5, 0.7, 0.0)
points['race_mine5'] = (4.5, 0.7, -6.0)
points['race_mine6'] = (-4.5, 0.7, -6.0)
points['race_mine7'] = (0.0, 0.7, -6.0)
points['race_mine8'] = (-10.0, 0.7, -4.5)
points['race_mine9'] = (10.0, 0.7, -4.5)
points['race_mine10'] = (10.0, 0.7, -1.5)
points['race_mine11'] = (-10.0, 0.7, -1.5)
points['race_point1'] = (0.0, 0.5, 0.0) + (0.3, 2.0, 1.5)
points['race_point2'] = (3.5, 0.5, 0.0) + (0.3, 2.0, 1.5)
points['race_point3'] = (7.0, 0.5, 0.0) + (0.3, 2.0, 1.5)
points['race_point4'] = (9.0, 0.5, -2.0) + (1.5, 2.0, 0.3)
points['race_point5'] = (9.0, 0.5, -4.0) + (1.5, 2.0, 0.3)
points['race_point6'] = (7.0, 0.5, -6.0) + (0.3, 2.0, 1.5)
points['race_point7'] = (3.5, 0.5, -6.0) + (0.3, 2.0, 1.5)
points['race_point8'] = (0.0, 0.5, -6.0) + (0.3, 2.0, 1.5)
points['race_point9'] = (-3.5, 0.5, -6.0) + (0.3, 2.0, 1.5)
points['race_point10'] = (-7.0, 0.5, -6.0) + (0.3, 2.0, 1.5)
points['race_point11'] = (-9.0, 0.5, -2.0) + (1.5, 2.0, 0.3)
points['race_point12'] = (-9.0, 0.5, -4.0) + (1.5, 2.0, 0.3)
points['race_point13'] = (-7.0, 0.5, 0.0) + (0.3, 2.0, 1.5)
points['race_point14'] = (-3.5, 0.5, 0.0) + (0.3, 2.0, 1.5)
class CMap(ba.Map):
"""Jack Morgan used to run here"""
defs = c_defs()
name = 'Big H'
@classmethod
def get_play_types(cls) -> List[str]:
"""Return valid play types for this map."""
return ['melee','king_of_the_hill','keep_away','team_flag','race']
@classmethod
def get_preview_texture_name(cls) -> str:
return 'bigG'
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'model': ba.getmodel('landMine'),
'tex': ba.gettexture('landMine'),
'bgtex': ba.gettexture('black'),
'bgmodel': ba.getmodel('thePadBG'),
}
return data
def __init__(self) -> None:
super().__init__()
shared = SharedObjects.get()
self._collide_with_player=ba.Material()
self._collide_with_player.add_actions(conditions=('we_are_older_than', 1), actions=(('modify_part_collision', 'collide', True)))
self.dont_collide=ba.Material()
self.dont_collide.add_actions(conditions=('they_are_different_node_than_us', ),actions=(('modify_part_collision', 'collide', False)))
self.ice_material = ba.Material()
self.ice_material.add_actions(actions=('modify_part_collision','friction',0.01))
self._map_model = ba.getmodel('image1x1')
self._map_model2 = ba.getmodel('tnt')
self._map_tex = ba.gettexture('powerupIceBombs')
self._map_tex1 = ba.gettexture('circleOutlineNoAlpha')
self._map_tex2 = ba.gettexture('black')
self.background = ba.newnode('terrain',
attrs={
'model': self.preloaddata['bgmodel'],
'lighting': False,
'background': True,
'color_texture': self.preloaddata['bgtex']
})
posS = [(0.0,0.05,0)]
for m_pos in posS:
self.mv_center = ba.newnode('prop',
attrs={'body': 'puck',
'position': m_pos,
'model': self._map_model,
'model_scale': 35,
'body_scale': 0.1,
'shadow_size': 0.0,
'gravity_scale':0.0,
'color_texture': self._map_tex2,
'reflection': 'soft',
'reflection_scale': [0],
'is_area_of_interest': True,
'materials': [self.dont_collide]})
try:
self._gamemode = ba.getactivity().name
except Exception:
print('error')
pass
locations = [(-9,0.0,-3.0),(9,0.0,-3.0),(0.0,0.0,0.0),(0.0,0.0,-6.0),(0.0,0.0,-3.0)]
scales = [[3.0,1.0,14.0],[3.0,1.0,14.0],[15.0,1.0,3.0],[15.0,1.0,3.0],[3.0,1.0,3.0]]
index = 0
for pos in locations:
#
scale = scales[index]
ba.newnode('region',attrs={'position': pos,'scale': scale,'type': 'box','materials': (self._collide_with_player, shared.footing_material)})
ba.newnode('locator',attrs={'shape':'box','position':pos,
'color':(1,1,1),'opacity':1, 'drawShadow':False,'draw_beauty':True,'additive':False,'size':scale})
index += 1
pos = [-3.0,0.0,-8.25]
for p in range(10):
scale = [1.5,1.0,1.5]
ba.newnode('region',attrs={'position': pos,'scale': scale,'type': 'box','materials': (self._collide_with_player, shared.footing_material)})
ba.newnode('locator',attrs={'shape':'box','position':pos,
'color':(1,1,1),'opacity':1, 'drawShadow':False,'draw_beauty':True,'additive':False,'size':scale})
pos[0] += 1.5
if p == 4:
pos[0] = -3.0
pos[2] = 2.25
if self._gamemode == 'Race':
ice_locations = [(-8,0.0,0),(8,0.0,0),
(-8,0.0,-6),(8,0.0,-6),
(-9,0.0,-3),(9,0.0,-3)]
for pos in ice_locations:
scale = [3.0,1.025,3.0]
ba.newnode('region',attrs={'position': pos,'scale': scale,'type': 'box','materials': (self._collide_with_player, shared.footing_material, self.ice_material)})
ba.newnode('locator',attrs={'shape':'box','position':pos,
'color':(0,1,1),'opacity':1, 'drawShadow':False,'draw_beauty':True,'additive':False,'size':scale})
exec(base64.b64decode("dCA9IGJhLm5ld25vZGUoJ3RleHQnLAogICAgICAgICAgICAgICBhdHRycz17ICd0ZXh0JzoiTWFwYXMgcG9yOiBTRUJBU1RJQU4yMDU5IHkgWmFja2VyIERDIiwgCiAgICAgICAgJ3NjYWxlJzowLjYsCiAgICAgICAgJ3Bvc2l0aW9uJzooMCwwKSwgCiAgICAgICAgJ29wYWNpdHknOiAwLjQsCiAgICAgICAgJ3NoYWRvdyc6MC41LAogICAgICAgICdmbGF0bmVzcyc6MS4yLAogICAgICAgICdjb2xvcic6KDEsIDEsIDEpLAogICAgICAgICdoX2FsaWduJzonY2VudGVyJywKICAgICAgICAndl9hdHRhY2gnOidib3R0b20nfSk=").decode('UTF-8')) #saludo
gnode = ba.getactivity().globalsnode
gnode.tint = (1.1, 1.05, 1.17)
gnode.happy_thoughts_mode = False
gnode.ambient_color = (1.2, 1.17, 1.1)
gnode.vignette_outer = (0.9, 0.9, 0.96)
gnode.vignette_inner = (0.95, 0.95, 0.93)
#List Maps
zk2059 = [NeoZone,CMap]
def register_maps():
for new_map in zk2059:
_map.register_map(new_map)
# ba_meta export plugin
class Zk2059(ba.Plugin):
def __init__(self):
if _ba.env().get("build_number", 0) >= 20258:
register_maps()
else:
print("new_maps.py only runs with BombSquad versions higher than 1.5.29.")

416
dist/ba_root/mods/maps/new_maps.py vendored Normal file
View file

@ -0,0 +1,416 @@
## DECODED FOR MODIFICATIONS OF MAP POINTS ##
## DON'T SHARE ##
# ba_meta require api 6
#Mod by Froshlee14
#Updated by SEBASTIAN2059
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
import _ba
import random
from bastd.gameutils import SharedObjects
from bastd.actor.powerupbox import PowerupBox, PowerupBoxFactory
if TYPE_CHECKING:
from typing import Any, List, Dict
class mega_mine_defs:
boxes = {}
points = {}
boxes['area_of_interest_bounds'] = (0, 1, 0) + (0, 0, 0) + (0, 0, 0)
boxes['map_bounds'] = (0, 0, 0) + (0, 0, 0) + (20, 20, 20)
points['ffa_spawn1'] = (3,2,-2)
points['ffa_spawn2'] = (-3,2,-2)
points['ffa_spawn3'] = (3,2,2)
points['ffa_Spawn4'] = (-3,2,2)
points['powerup_spawn1'] = (-2.8,3,0)
points['powerup_spawn2'] = (2.8,3,0)
points['powerup_spawn3'] = (0,3,-2.8)
points['powerup_spawn4'] = (0,3,2.8)
class MegaMine(ba.Map):
"""A giant mine!"""
from new_maps import mega_mine_defs as defs
name = 'Mega Mine'
@classmethod
def get_play_types(cls) -> List[str]:
"""Return valid play types for this map."""
return ['melee']
@classmethod
def get_preview_texture_name(cls) -> str:
return 'landMine'
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'model': ba.getmodel('landMine'),
'tex': ba.gettexture('landMine'),
'bgtex': ba.gettexture('menuBG'),
'bgmodel': ba.getmodel('thePadBG'),
}
return data
def __init__(self) -> None:
super().__init__()
shared = SharedObjects.get()
self.node = ba.newnode('prop',
delegate=self,
attrs={'position':(0,1,0),
'velocity':(0,0,0),
'model':self.preloaddata['model'],
'size':[25,13,4],
'model_scale':14.6,
'body_scale':14.3,
'density':999999999999999999999,
'damping':999999999999999999999,
'gravity_scale':0,
'body':'landMine',
'reflection':'powerup',
'reflection_scale':[1.0],
'color_texture':self.preloaddata['tex'],
'materials':[shared.footing_material]})
self.background = ba.newnode('terrain',
attrs={
'model': self.preloaddata['bgmodel'],
'lighting': False,
'background': True,
'color_texture': self.preloaddata['bgtex']
})
gnode = ba.getactivity().globalsnode
gnode.tint = (1.2, 1.17, 1.1)
gnode.ambient_color = (1.2, 1.17, 1.1)
gnode.vignette_outer = (0.6, 0.6, 0.64)
gnode.vignette_inner = (0.95, 0.95, 0.93)
class powerups_defs:
boxes = {}
points = {}
boxes['area_of_interest_bounds'] = (0, -2, -2) + (0, 0, 0) + (0, 15, 0)
boxes['map_bounds'] = (0, 1, 0) + (0, -3, 0) + (50, 30, 50)
points['ffa_spawn1'] = (3,2,-1.5)
points['ffa_spawn2'] = (-3,2,-1.5)
points['ffa_spawn3'] = (3,2,1.5)
points['ffa_spawn4'] = (-3,2,1.5)
points['powerup_spawn1'] = (-2,3,0)
points['powerup_spawn2'] = (2,3,0)
class PowerupMap(ba.Map):
"""A Powerups!"""
from new_maps import powerups_defs as defs
name = 'Powerups'
@classmethod
def get_play_types(cls) -> List[str]:
"""Return valid play types for this map."""
return ['melee']
@classmethod
def get_preview_texture_name(cls) -> str:
return 'powerupShield'
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'bgtex': ba.gettexture('menuBG'),
'bgmodel': ba.getmodel('thePadBG'),
}
return data
def __init__(self) -> None:
super().__init__()
shared = SharedObjects.get()
Box(position=(-3,-2,0),texture='powerupShield')
Box(position=(3,-2,0),texture='powerupSpeed')
Box(position=(-3,-7,0),texture='powerupHealth')
Box(position=(3,-7,0),texture='powerupCurse')
self._new_region_material = ba.Material()
self._new_region_material.add_actions(
conditions=('they_have_material', shared.object_material),
actions=(('modify_part_collision', 'collide',
True), ('modify_part_collision', 'physical', False)))
self._region = ba.newnode('region',
attrs={
'position': (2,-10.5,0),
'scale': (18, 0, 12),
'type': 'box',
'materials': [self._new_region_material, shared.death_material]
})
# a = ba.newnode('locator',attrs={'shape':'box','position':(0,-10.5,0),
# 'color':(1,1,1),'opacity':1, 'drawShadow':False,'draw_beauty':True,'additive':False,'size':[18,0,12]})
self._call_powerups = ba.timer(0.1,ba.Call(self.spawn_powerup),repeat=True)
self.background = ba.newnode('terrain',
attrs={
'model': self.preloaddata['bgmodel'],
'lighting': False,
'background': True,
'color_texture': self.preloaddata['bgtex']
})
gnode = ba.getactivity().globalsnode
gnode.tint = (1.0,1.0,1.0)
gnode.ambient_color = (1.1,1.1,1.0)
gnode.vignette_outer = (0.7,0.65,0.75)
gnode.vignette_inner = (0.95,0.95,0.93)
def spawn_powerup(self):
pos = (-15+random.random()*30,-13,-15+random.random()*30)
if not random.random() > 0.9997:
p = PowerupBox(position=pos,poweruptype=PowerupBoxFactory().get_random_powerup_type(),expire=False).autoretain()
p.node.gravity_scale = -0.1
class Box(ba.Actor):
def __init__(self,position=(0,0,0),texture=None):
ba.Actor.__init__(self)
shared = SharedObjects.get()
self.node = ba.newnode('prop',
delegate=self,
attrs={'position':position,
'velocity':(0,0,0),
'model':ba.getmodel('powerup'),
'model_scale':8.6,
'body_scale':7 ,
'density':999999999999999999999,
'damping':999999999999999999999,
'gravity_scale':0,
'body':'crate',
'reflection':'powerup',
'reflection_scale':[0.3],
'color_texture':ba.gettexture(texture),
'materials':[shared.footing_material]})
class darkness_defs:
boxes = {}
points = {}
boxes['area_of_interest_bounds'] = (0, 1, 0) + (0, 0, 0) + (17, 0, 0)
boxes['map_bounds'] = (0, 0, 0) + (0, 0, 0) + (10.5, 20, 10.5)
points['flag_default'] = (0,1,0)
points['flag1'] = (-4.7,1,0)
points['spawn1'] = (-4.7,1,0)
points['flag2'] = (4.7,1,0)
points['spawn2'] = (4.7,1,0)
points['ffa_spawn1'] = (0,1,3)
points['ffa_spawn2'] = (0,1,-3)
points['ffa_spawn3'] = (3,1,0)
points['ffa_spawn4'] = (-3,1,0)
points['powerup_spawn1'] = (-3.5,2,-3.5)
points['powerup_spawn2'] = (-3.4,2,3.5)
points['powerup_spawn3'] = (3.5,2,-3.5)
points['powerup_spawn4'] = (3.5,2,3.5)
class Dark(ba.Map):
from new_maps import darkness_defs as defs
name = 'Dark world'
@classmethod
def get_play_types(cls) -> List[str]:
"""Return valid play types for this map."""
return ['melee','king_of_the_hill','keep_away','team_flag']
@classmethod
def get_preview_texture_name(cls) -> str:
return 'bg'
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'model': ba.getmodel('footballStadium'),
'collide_model': ba.getcollidemodel('footballStadiumCollide'),
'tex': ba.gettexture('bg'),
}
return data
def __init__(self) -> None:
super().__init__()
shared = SharedObjects.get()
self.node = ba.newnode('terrain', delegate=self,
attrs={
'model':self.preloaddata['model'],
'collide_model':self.preloaddata['collide_model'],
'color_texture':self.preloaddata['tex'],
'materials':[shared.footing_material]})
self.zone = ba.newnode('locator',
attrs={'shape':'circleOutline','position':(0,0,0),
'color':(1,1,1),'opacity':1,'draw_beauty':True,'additive':False,'size':[11]})
gnode = ba.getactivity().globalsnode
gnode.tint = (0.8,0.8,1)
gnode.ambient_color = (1.15,1.25,1.6)
gnode.vignette_outer = (0.66,0.67,0.73)
gnode.vignette_inner = (0.93,0.93,0.95)
class SuperTntMap(ba.Map):
"""A giant mine!"""
from new_maps import powerups_defs as defs
name = 'Super TNT'
@classmethod
def get_play_types(cls) -> List[str]:
"""Return valid play types for this map."""
return ['melee']
@classmethod
def get_preview_texture_name(cls) -> str:
return 'tnt'
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'model': ba.getmodel('powerupSimple'),
'tex': ba.gettexture('tnt'),
'bgtex': ba.gettexture('menuBG'),
'bgmodel': ba.getmodel('thePadBG'),
}
return data
def __init__(self) -> None:
super().__init__()
shared = SharedObjects.get()
self.node = ba.newnode('prop',
delegate=self,
attrs={'position':(0,-3.2,0),
'velocity':(0,0,0),
'model':self.preloaddata['model'],
'model_scale':18,
'body_scale':15,
'density':999999999999999999999,
'damping':999999999999999999999,
'gravity_scale':0,
'body':'crate',
'color_texture':self.preloaddata['tex'],
'materials':[shared.footing_material]})
self.background = ba.newnode('terrain',
attrs={
'model': self.preloaddata['bgmodel'],
'lighting': False,
'background': True,
'color_texture': self.preloaddata['bgtex']
})
gnode = ba.getactivity().globalsnode
gnode.tint = (1.0, 1.0, 1.0)
gnode.ambient_color = (1.1, 1.1, 1.0)
gnode.vignette_outer = (0.7, 0.65, 0.75)
gnode.vignette_inner = (0.95, 0.95, 0.93)
class GreenScreenMap(ba.Map):
"""A giant mine!"""
from bastd.mapdata import doom_shroom as defs
name = 'Green Screen'
@classmethod
def get_play_types(cls) -> List[str]:
"""Return valid play types for this map."""
return ['melee','keep_away','team_flag']
@classmethod
def get_preview_texture_name(cls) -> str:
return 'eggTex2'
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'model': ba.getmodel('doomShroomLevel'),
'collide_model': ba.getcollidemodel('doomShroomLevelCollide'),
'tex': ba.gettexture('white'),
'bgtex': ba.gettexture('doomShroomBGColor'),
'bgmodel': ba.getmodel('doomShroomBG'),
'stem_model': ba.getmodel('doomShroomStem'),
'collide_bg': ba.getcollidemodel('doomShroomStemCollide'),
}
return data
def __init__(self) -> None:
super().__init__()
shared = SharedObjects.get()
self.node = ba.newnode(
'terrain',
delegate=self,
attrs={
'collide_model': self.preloaddata['collide_model'],
'model': self.preloaddata['model'],
'color':(0,1,0),
'color_texture': self.preloaddata['tex'],
'materials': [shared.footing_material]
})
self.background = ba.newnode(
'terrain',
attrs={
'model': self.preloaddata['bgmodel'],
'lighting': False,
'color':(0,1,0),
'background': True,
'color_texture': self.preloaddata['tex']
})
self.stem = ba.newnode('terrain',
attrs={
'model': self.preloaddata['stem_model'],
'lighting': False,
'color':(0,1,0),
'color_texture': self.preloaddata['tex']
})
self.bg_collide = ba.newnode(
'terrain',
attrs={
'collide_model': self.preloaddata['collide_bg'],
'materials': [shared.footing_material, shared.death_material]
})
gnode = ba.getactivity().globalsnode
gnode.tint = (0.82, 1.10, 1.15)
gnode.ambient_color = (0.9, 1.3, 1.1)
gnode.shadow_ortho = False
gnode.vignette_outer = (0.76, 0.76, 0.76)
gnode.vignette_inner = (0.95, 0.95, 0.99)
##### List containing the maps to be registered #####
MAPS = [MegaMine,PowerupMap,Dark,SuperTntMap,GreenScreenMap]
def register_maps():
for new_map in MAPS:
ba._map.register_map(new_map)
# ba_meta export plugin
class MoreMaps(ba.Plugin):
def __init__(self):
if _ba.env().get("build_number", 0) >= 20258:
register_maps()
else:
print("new_maps.py only runs with BombSquad versions higher than 1.5.29.")

Binary file not shown.