Needs some testing

This commit is contained in:
brostosjoined 2024-01-17 23:09:18 +03:00
parent 1bce1d7d76
commit 4719c3e718
23 changed files with 2124 additions and 1626 deletions

View file

@ -68,10 +68,10 @@ class ForestMap(bs.Map):
def on_preload(cls) -> any:
data: dict[str, any] = {
'mesh': bs.getmesh('natureBackground'),
'tex': bui.gettexture('natureBackgroundColor'),
'tex': bs.gettexture('natureBackgroundColor'),
'collision_mesh': bs.getcollisionmesh('natureBackgroundCollide'),
'bgmesh': bs.getmesh('thePadBG'),
'bgtex': bui.gettexture('menuBG')
'bgtex': bs.gettexture('menuBG')
}
return data
@ -85,7 +85,7 @@ class ForestMap(bs.Map):
attrs={
'mesh': self.preloaddata['mesh'],
'color_texture': self.preloaddata['tex'],
'collide_mesh': self.preloaddata['collide_mesh'],
'collision_mesh': self.preloaddata['collision_mesh'],
'materials': [shared.footing_material]
}
)

View file

@ -77,6 +77,7 @@
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "2fda676",
@ -92,10 +93,11 @@
{
"name": "JoseAng3l",
"email": "",
"discord": "! JoseANG3L#0268"
"discord": "joseang3l"
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "2fda676",
@ -111,10 +113,11 @@
{
"name": "JoseAng3l",
"email": "",
"discord": "! JoseANG3L#0268"
"discord": "joseang3l"
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "2fda676",
@ -130,10 +133,11 @@
{
"name": "JoseAng3l",
"email": "",
"discord": "! JoseANG3L#0268"
"discord": "joseang3l"
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "2fda676",
@ -149,7 +153,7 @@
{
"name": "JoseAng3l",
"email": "",
"discord": "! JoseANG3L#0268"
"discord": "joseang3l"
}
],
"versions": {
@ -178,6 +182,7 @@
}
],
"versions": {
"1.1.0": null,
"1.0.1": {
"api_version": 7,
"commit_sha": "d511c15",
@ -199,10 +204,11 @@
{
"name": "Cross Joy",
"email": "cross.joy.official@gmail.com",
"discord": "Cross Joy#0721"
"discord": "crossjoy"
}
],
"versions": {
"1.0.0": null,
"2.0.0": {
"api_version": 7,
"commit_sha": "8b257b3",
@ -328,6 +334,7 @@
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "0841b9e",
@ -343,7 +350,7 @@
{
"name": "SEBASTIAN2059",
"email": "",
"discord": "SEBASTIAN2059#5751"
"discord": "sebastian2059"
},
{
"name": "zPanxo",
@ -373,10 +380,11 @@
{
"name": "Mr.Smoothy",
"email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824"
"discord": "mr.smoothy"
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "52094fc",
@ -392,7 +400,7 @@
{
"name": "Mr.Smoothy",
"email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824"
"discord": "mr.smoothy"
}
],
"versions": {
@ -417,10 +425,11 @@
{
"name": "Mr.Smoothy",
"email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824"
"discord": "mr.smoothy"
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "2aa1e50",
@ -436,7 +445,7 @@
{
"name": "Mr.Smoothy",
"email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824"
"discord": "mr.smoothy"
}
],
"versions": {
@ -455,10 +464,11 @@
{
"name": "Mr.Smoothy",
"email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824"
"discord": "mr.smoothy"
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "2aa1e50",
@ -474,10 +484,11 @@
{
"name": "Mr.Smoothy",
"email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824"
"discord": "mr.smoothy"
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "52094fc",
@ -534,7 +545,7 @@
{
"name": "JoseAng3l",
"email": "",
"discord": "! JoseANG3L#0268"
"discord": "joseang3l"
}
],
"versions": {
@ -588,6 +599,7 @@
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "7219487",
@ -603,10 +615,11 @@
{
"name": "ThePersonMan",
"email": "",
"discord": "ThePersonMan#0276"
"discord": "the.personman"
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "7219487",
@ -622,10 +635,11 @@
{
"name": "Dliwk",
"email": "",
"discord": "Dliwk#7961"
"discord": "dliwk"
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "7219487",
@ -645,6 +659,7 @@
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "7219487",
@ -660,10 +675,11 @@
{
"name": "SEBASTIAN2059",
"email": "",
"discord": "SEBASTIAN2059#5751"
"discord": "sebastian2059"
}
],
"versions": {
"1.0.1": null,
"1.0.0": {
"api_version": 7,
"commit_sha": "7219487",
@ -698,7 +714,7 @@
{
"name": "Cross Joy",
"email": "cross.joy.official@gmail.com",
"discord": "Cross Joy#0721"
"discord": "crossjoy"
}
],
"versions": {

View file

@ -1,20 +1,21 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# Released under the MIT License. See LICENSE for details.
# BY Stary_Agent
"""Hockey game and support classes."""
# ba_meta require api 7
# ba_meta require api 8
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
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
import babase
import bascenev1 as bs
from bascenev1lib.actor.playerspaz import PlayerSpaz
from bascenev1lib.actor.scoreboard import Scoreboard
from bascenev1lib.actor.powerupbox import PowerupBoxFactory
from bascenev1lib.gameutils import SharedObjects
if TYPE_CHECKING:
from typing import Any, Sequence, Dict, Type, List, Optional, Union
@ -32,13 +33,13 @@ def create_slope(self):
x = 5
y = 12
for i in range(0, 10):
ba.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (0.2, 0.1, 6),
bs.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (0.2, 0.1, 6),
'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
x = x+0.3
y = y+0.1
class Puck(ba.Actor):
class Puck(bs.Actor):
"""A lovely giant hockey puck."""
def __init__(self, position: Sequence[float] = (0.0, 13.0, 0.0)):
@ -53,10 +54,10 @@ class Puck(ba.Actor):
assert activity is not None
assert isinstance(activity, HockeyGame)
pmats = [shared.object_material, activity.puck_material]
self.node = ba.newnode('prop',
self.node = bs.newnode('prop',
delegate=self,
attrs={
'model': activity.puck_model,
'mesh': activity.puck_mesh,
'color_texture': activity.puck_tex,
'body': 'sphere',
'reflection': 'soft',
@ -67,10 +68,10 @@ class Puck(ba.Actor):
'position': self._spawn_pos,
'materials': pmats
})
ba.animate(self.node, 'model_scale', {0: 0, 0.2: 1.3, 0.26: 1})
bs.animate(self.node, 'mesh_scale', {0: 0, 0.2: 1.3, 0.26: 1})
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
if isinstance(msg, bs.DieMessage):
assert self.node
self.node.delete()
activity = self._activity()
@ -78,11 +79,11 @@ class Puck(ba.Actor):
activity.handlemessage(PuckDiedMessage(self))
# If we go out of bounds, move back to where we started.
elif isinstance(msg, ba.OutOfBoundsMessage):
elif isinstance(msg, bs.OutOfBoundsMessage):
assert self.node
self.node.position = self._spawn_pos
elif isinstance(msg, ba.HitMessage):
elif isinstance(msg, bs.HitMessage):
assert self.node
assert msg.force_direction is not None
self.node.handlemessage(
@ -103,31 +104,31 @@ class Puck(ba.Actor):
super().handlemessage(msg)
class Player(ba.Player['Team']):
class Player(bs.Player['Team']):
"""Our player type for this game."""
class Team(ba.Team[Player]):
class Team(bs.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.score = 0
# ba_meta export game
class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
# ba_meta export bascenev1.GameActivity
class AirSoccerGame(bs.TeamGameActivity[Player, Team]):
"""Ice hockey game."""
name = 'Epic Air Soccer'
description = 'Score some goals.'
available_settings = [
ba.IntSetting(
bs.IntSetting(
'Score to Win',
min_value=1,
default=1,
increment=1,
),
ba.IntChoiceSetting(
bs.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
@ -139,7 +140,7 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
],
default=0,
),
ba.FloatChoiceSetting(
bs.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.1),
@ -151,14 +152,14 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
default=1.0,
),
]
default_music = ba.MusicType.HOCKEY
default_music = bs.MusicType.HOCKEY
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.DualTeamSession)
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
return issubclass(sessiontype, bs.DualTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
return ['Creative Thoughts']
def __init__(self, settings: dict):
@ -166,16 +167,16 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
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._cheer_sound = bs.getsound('cheer')
self._chant_sound = bs.getsound('crowdChant')
self._foghorn_sound = bs.getsound('foghorn')
self._swipsound = bs.getsound('swip')
self._whistle_sound = bs.getsound('refWhistle')
self.puck_mesh = bs.getmesh('bomb')
self.puck_tex = bs.gettexture('landMine')
self.puck_scored_tex = bs.gettexture('landMineLit')
self._puck_sound = bs.getsound('metalHit')
self.puck_material = bs.Material()
self.puck_material.add_actions(actions=(('modify_part_collision',
'friction', 0.5)))
self.puck_material.add_actions(conditions=('they_have_material',
@ -194,7 +195,7 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
shared.footing_material),
actions=('impact_sound',
self._puck_sound, 0.2, 5))
self._real_wall_material = ba.Material()
self._real_wall_material = bs.Material()
self._real_wall_material.add_actions(
actions=(
@ -210,7 +211,7 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
('modify_part_collision', 'physical', True)
))
self._goal_post_material = ba.Material()
self._goal_post_material = bs.Material()
self._goal_post_material.add_actions(
actions=(
@ -237,15 +238,15 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
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()
('message', 'their_node', 'at_connect', bs.DieMessage())))
self._score_region_material = bs.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._score_regions: Optional[List[bs.NodeActor]] = None
self._puck: Optional[Puck] = None
self._score_to_win = int(settings['Score to Win'])
self._time_limit = float(settings['Time Limit'])
@ -273,8 +274,8 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
defs = self.map.defs
self._score_regions = []
self._score_regions.append(
ba.NodeActor(
ba.newnode('region',
bs.NodeActor(
bs.newnode('region',
attrs={
'position': (17, 14.5, -5.52),
'scale': (1, 3, 1),
@ -282,8 +283,8 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
'materials': [self._score_region_material]
})))
self._score_regions.append(
ba.NodeActor(
ba.newnode('region',
bs.NodeActor(
bs.newnode('region',
attrs={
'position': (-17, 14.5, -5.52),
'scale': (1, 3, 1),
@ -291,36 +292,36 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
'materials': [self._score_region_material]
})))
self._update_scoreboard()
ba.playsound(self._chant_sound)
self._chant_sound.play()
def on_team_join(self, team: Team) -> None:
self._update_scoreboard()
def _handle_puck_player_collide(self) -> None:
collision = ba.getcollision()
collision = bs.getcollision()
try:
puck = collision.sourcenode.getdelegate(Puck, True)
player = collision.opposingnode.getdelegate(PlayerSpaz,
True).getplayer(
Player, True)
except ba.NotFoundError:
except bs.NotFoundError:
return
puck.last_players_to_touch[player.team.id] = player
def make_map(self):
shared = SharedObjects.get()
_ba.get_foreground_host_activity()._map.leftwall.materials = [
bs.get_foreground_host_activity()._map.leftwall.materials = [
shared.footing_material, self._real_wall_material]
_ba.get_foreground_host_activity()._map.rightwall.materials = [
bs.get_foreground_host_activity()._map.rightwall.materials = [
shared.footing_material, self._real_wall_material]
_ba.get_foreground_host_activity()._map.topwall.materials = [
bs.get_foreground_host_activity()._map.topwall.materials = [
shared.footing_material, self._real_wall_material]
self.floorwall = ba.newnode('region', attrs={'position': (0, 5, -5.52), 'scale': (
self.floorwall = bs.newnode('region', attrs={'position': (0, 5, -5.52), 'scale': (
35.4, 0.2, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.newnode('locator', attrs={'shape': 'box', 'position': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (
0, 5, -5.52), 'color': (0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (35.4, 0.2, 2)})
self.create_goal_post(-16.65, 12.69)
@ -343,9 +344,9 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
floor += "_ "
shared = SharedObjects.get()
step = {}
step["r"] = ba.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (
step["r"] = bs.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (
3, 0.1, 6), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.newnode('locator', attrs={'shape': 'box', 'position': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (
x, y, -5.52), 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (3, 0.1, 2)})
return step
@ -359,10 +360,10 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
floor = ""
for i in range(0, 4):
floor += "_ "
ba.newnode('region', attrs={'position': (x-0.2, y, -5.52), 'scale': (1.8, 0.1, 6),
bs.newnode('region', attrs={'position': (x-0.2, y, -5.52), 'scale': (1.8, 0.1, 6),
'type': 'box', 'materials': [shared.footing_material, self._goal_post_material]})
ba.newnode('locator', attrs={'shape': 'box', 'position': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (
x-0.2, y, -5.52), 'color': color, 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (1.8, 0.1, 2)})
def create_vertical(self, x, y):
@ -370,9 +371,9 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
floor = ""
for i in range(0, 4):
floor += "|\n"
ba.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (0.1, 2.8, 1),
bs.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (0.1, 2.8, 1),
'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.newnode('locator', attrs={'shape': 'box', 'position': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (
x, y, -5.52), 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (0.1, 2.8, 2)})
def spawn_player_spaz(self,
@ -402,7 +403,7 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
if self._puck.scored:
return
region = ba.getcollision().sourcenode
region = bs.getcollision().sourcenode
index = 0
for index in range(len(self._score_regions)):
if region == self._score_regions[index].node:
@ -416,7 +417,7 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
# Tell all players to celebrate.
for player in team.players:
if player.actor:
player.actor.handlemessage(ba.CelebrateMessage(2.0))
player.actor.handlemessage(bs.CelebrateMessage(2.0))
# If we've got the player from the scoring team that last
# touched us, give them points.
@ -431,30 +432,30 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
if team.score >= self._score_to_win:
self.end_game()
ba.playsound(self._foghorn_sound)
ba.playsound(self._cheer_sound)
self._foghorn_sound.play()
self._cheer_sound.play()
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)
bs.timer(1.0, self._kill_puck)
light = ba.newnode('light',
light = bs.newnode('light',
attrs={
'position': ba.getcollision().position,
'position': bs.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)
bs.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
bs.timer(1.0, light.delete)
ba.cameraflash(duration=10.0)
bs.cameraflash(duration=10.0)
self._update_scoreboard()
def end_game(self) -> None:
results = ba.GameResults()
results = bs.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)
@ -467,7 +468,7 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
def handlemessage(self, msg: Any) -> Any:
# Respawn dead players if they're still in the game.
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.PlayerDiedMessage):
# Augment standard behavior...
super().handlemessage(msg)
self.respawn_player(msg.getplayer(Player))
@ -475,23 +476,23 @@ class AirSoccerGame(ba.TeamGameActivity[Player, Team]):
# Respawn dead pucks.
elif isinstance(msg, PuckDiedMessage):
if not self.has_ended():
ba.timer(3.0, self._spawn_puck)
bs.timer(3.0, self._spawn_puck)
else:
super().handlemessage(msg)
def _flash_puck_spawn(self) -> None:
light = ba.newnode('light',
light = bs.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)
bs.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True)
bs.timer(1.0, light.delete)
def _spawn_puck(self) -> None:
ba.playsound(self._swipsound)
ba.playsound(self._whistle_sound)
self._swipsound.play()
self._whistle_sound.play()
self._flash_puck_spawn()
assert self._puck_spawn_pos is not None
self._puck = Puck(position=self._puck_spawn_pos)
@ -541,7 +542,7 @@ class mapdefs:
0.5245740665, 0.5245740665, 0.01941146064)
class CreativeThoughts(ba.Map):
class CreativeThoughts(bs.Map):
"""Freaking map by smoothy."""
defs = mapdefs
@ -562,26 +563,26 @@ class CreativeThoughts(ba.Map):
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'model': ba.getmodel('alwaysLandLevel'),
'bottom_model': ba.getmodel('alwaysLandLevelBottom'),
'bgmodel': ba.getmodel('alwaysLandBG'),
'collide_model': ba.getcollidemodel('alwaysLandLevelCollide'),
'tex': ba.gettexture('alwaysLandLevelColor'),
'bgtex': ba.gettexture('alwaysLandBGColor'),
'vr_fill_mound_model': ba.getmodel('alwaysLandVRFillMound'),
'vr_fill_mound_tex': ba.gettexture('vrFillMound')
'mesh': bs.getmesh('alwaysLandLevel'),
'bottom_mesh': bs.getmesh('alwaysLandLevelBottom'),
'bgmesh': bs.getmesh('alwaysLandBG'),
'collision_mesh': bs.getcollisionmesh('alwaysLandLevelCollide'),
'tex': bs.gettexture('alwaysLandLevelColor'),
'bgtex': bs.gettexture('alwaysLandBGColor'),
'vr_fill_mound_mesh': bs.getmesh('alwaysLandVRFillMound'),
'vr_fill_mound_tex': bs.gettexture('vrFillMound')
}
return data
@classmethod
def get_music_type(cls) -> ba.MusicType:
return ba.MusicType.FLYING
def get_music_type(cls) -> bs.MusicType:
return bs.MusicType.FLYING
def __init__(self) -> None:
super().__init__(vr_overlay_offset=(0, -3.7, 2.5))
shared = SharedObjects.get()
self._fake_wall_material = ba.Material()
self._real_wall_material = ba.Material()
self._fake_wall_material = bs.Material()
self._real_wall_material = bs.Material()
self._fake_wall_material.add_actions(
conditions=(('they_are_younger_than', 9000), 'and',
('they_have_material', shared.player_material)),
@ -597,29 +598,29 @@ class CreativeThoughts(ba.Map):
('modify_part_collision', 'physical', True)
))
self.background = ba.newnode(
self.background = bs.newnode(
'terrain',
attrs={
'model': self.preloaddata['bgmodel'],
'mesh': self.preloaddata['bgmesh'],
'lighting': False,
'background': True,
'color_texture': ba.gettexture("rampageBGColor")
'color_texture': bs.gettexture("rampageBGColor")
})
self.leftwall = ba.newnode('region', attrs={'position': (-17.75152479, 13, -5.52), 'scale': (
self.leftwall = bs.newnode('region', attrs={'position': (-17.75152479, 13, -5.52), 'scale': (
0.1, 15.5, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
self.rightwall = ba.newnode('region', attrs={'position': (17.75, 13, -5.52), 'scale': (
self.rightwall = bs.newnode('region', attrs={'position': (17.75, 13, -5.52), 'scale': (
0.1, 15.5, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
self.topwall = ba.newnode('region', attrs={'position': (0, 21.0, -5.52), 'scale': (
self.topwall = bs.newnode('region', attrs={'position': (0, 21.0, -5.52), 'scale': (
35.4, 0.2, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.newnode('locator', attrs={'shape': 'box', 'position': (-17.75152479, 13, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (-17.75152479, 13, -5.52), 'color': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (0.1, 15.5, 2)})
ba.newnode('locator', attrs={'shape': 'box', 'position': (17.75, 13, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (17.75, 13, -5.52), 'color': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (0.1, 15.5, 2)})
ba.newnode('locator', attrs={'shape': 'box', 'position': (0, 21.0, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (0, 21.0, -5.52), 'color': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (35.4, 0.2, 2)})
gnode = ba.getactivity().globalsnode
gnode = bs.getactivity().globalsnode
gnode.happy_thoughts_mode = True
gnode.shadow_offset = (0.0, 8.0, 5.0)
gnode.tint = (1.3, 1.23, 1.0)
@ -630,9 +631,9 @@ class CreativeThoughts(ba.Map):
self.is_flying = True
# throw out some tips on flying
txt = ba.newnode('text',
txt = bs.newnode('text',
attrs={
'text': ba.Lstr(resource='pressJumpToFlyText'),
'text': babase.Lstr(resource='pressJumpToFlyText'),
'scale': 1.2,
'maxwidth': 800,
'position': (0, 200),
@ -641,7 +642,7 @@ class CreativeThoughts(ba.Map):
'h_align': 'center',
'v_attach': 'bottom'
})
cmb = ba.newnode('combine',
cmb = bs.newnode('combine',
owner=txt,
attrs={
'size': 4,
@ -649,12 +650,12 @@ class CreativeThoughts(ba.Map):
'input1': 0.9,
'input2': 0.0
})
ba.animate(cmb, 'input3', {3.0: 0, 4.0: 1, 9.0: 1, 10.0: 0})
bs.animate(cmb, 'input3', {3.0: 0, 4.0: 1, 9.0: 1, 10.0: 0})
cmb.connectattr('output', txt, 'color')
ba.timer(10.0, txt.delete)
bs.timer(10.0, txt.delete)
try:
ba._map.register_map(CreativeThoughts)
bs._map.register_map(CreativeThoughts)
except:
pass

View file

@ -1,19 +1,22 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# Released under the MIT License. See LICENSE for details.
# ba_meta require api 7
# ba_meta require api 8
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
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 import playerspaz as ps
from bastd import maps
import babase
import bauiv1 as bui
import bascenev1 as bs
import _babase
from bascenev1lib.actor.playerspaz import PlayerSpaz
from bascenev1lib.actor.scoreboard import Scoreboard
from bascenev1lib.actor.powerupbox import PowerupBoxFactory
from bascenev1lib.gameutils import SharedObjects
from bascenev1lib.actor import playerspaz as ps
from bascenev1lib import maps
if TYPE_CHECKING:
from typing import Any, Sequence, Dict, Type, List, Optional, Union
@ -22,7 +25,7 @@ bsuSpaz = None
def getlanguage(text, sub: str = ''):
lang = _ba.app.lang.language
lang = bs.app.lang.language
translate = {
"Name":
{"Spanish": "Baloncesto",
@ -60,7 +63,7 @@ class BallDiedMessage:
self.ball = ball
class Ball(ba.Actor):
class Ball(bs.Actor):
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)):
super().__init__()
shared = SharedObjects.get()
@ -76,10 +79,10 @@ class Ball(ba.Actor):
assert isinstance(activity, BasketGame)
pmats = [shared.object_material, activity.ball_material]
self.node = ba.newnode('prop',
self.node = bs.newnode('prop',
delegate=self,
attrs={
'model': activity.ball_model,
'mesh': activity.ball_mesh,
'color_texture': activity.ball_tex,
'body': 'sphere',
'reflection': 'soft',
@ -92,22 +95,22 @@ class Ball(ba.Actor):
'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})
bs.animate(self.node, 'mesh_scale', {0: 0, 0.2: scale*1.3, 0.26: scale})
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
if isinstance(msg, bs.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):
elif isinstance(msg, bs.OutOfBoundsMessage):
assert self.node
self.node.position = self._spawn_pos
self.node.velocity = (0.0, 0.0, 0.0)
elif isinstance(msg, ba.HitMessage):
elif isinstance(msg, bs.HitMessage):
assert self.node
assert msg.force_direction is not None
self.node.handlemessage(
@ -127,11 +130,11 @@ class Ball(ba.Actor):
super().handlemessage(msg)
class Player(ba.Player['Team']):
class Player(bs.Player['Team']):
"""Our player type for this game."""
class Team(ba.Team[Player]):
class Team(bs.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
@ -144,21 +147,21 @@ class Points:
postes['pal_0'] = (10.64702320098877, 0.0000000000000000, 0.0000000000000000)
postes['pal_1'] = (-10.64702320098877, 0.0000000000000000, 0.0000000000000000)
# ba_meta export game
# ba_meta export bascenev1.GameActivity
class BasketGame(ba.TeamGameActivity[Player, Team]):
class BasketGame(bs.TeamGameActivity[Player, Team]):
name = getlanguage('Name')
description = getlanguage('Info')
available_settings = [
ba.IntSetting(
bs.IntSetting(
'Score to Win',
min_value=1,
default=1,
increment=1,
),
ba.IntChoiceSetting(
bs.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
@ -170,7 +173,7 @@ class BasketGame(ba.TeamGameActivity[Player, Team]):
],
default=0,
),
ba.FloatChoiceSetting(
bs.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
@ -181,38 +184,38 @@ class BasketGame(ba.TeamGameActivity[Player, Team]):
],
default=1.0,
),
ba.BoolSetting(getlanguage('S: Powerups'), default=True),
ba.BoolSetting(getlanguage('S: Velocity'), default=False),
ba.BoolSetting('Epic Mode', default=False),
bs.BoolSetting(getlanguage('S: Powerups'), default=True),
bs.BoolSetting(getlanguage('S: Velocity'), default=False),
bs.BoolSetting('Epic Mode', default=False),
]
default_music = ba.MusicType.HOCKEY
default_music = bs.MusicType.HOCKEY
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.DualTeamSession)
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
return issubclass(sessiontype, bs.DualTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
def get_supported_maps(cls, sessiontype: Type[bs.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._cheer_sound = bs.getsound('cheer')
self._chant_sound = bs.getsound('crowdChant')
self._foghorn_sound = bs.getsound('foghorn')
self._swipsound = bs.getsound('swip')
self._whistle_sound = bs.getsound('refWhistle')
self.ball_mesh = bs.getmesh('shield')
self.ball_tex = bs.gettexture('fontExtras3')
self._ball_sound = bs.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 = bs.Material()
self.ball_material.add_actions(actions=(('modify_part_collision',
'friction', 0.5)))
self.ball_material.add_actions(conditions=('they_have_material',
@ -238,14 +241,14 @@ class BasketGame(ba.TeamGameActivity[Player, Team]):
actions=(('call', 'at_connect',
self._handle_ball_player_collide), ))
self._score_region_material = ba.Material()
self._score_region_material = bs.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._score_regions: Optional[List[bs.NodeActor]] = None
self._ball: Optional[Ball] = None
self._score_to_win = int(settings['Score to Win'])
self._time_limit = float(settings['Time Limit'])
@ -270,8 +273,8 @@ class BasketGame(ba.TeamGameActivity[Player, Team]):
defs = self.map.defs
self._score_regions = []
self._score_regions.append(
ba.NodeActor(
ba.newnode('region',
bs.NodeActor(
bs.newnode('region',
attrs={
'position': defs.boxes['goal1'][0:3],
'scale': defs.boxes['goal1'][6:9],
@ -279,8 +282,8 @@ class BasketGame(ba.TeamGameActivity[Player, Team]):
'materials': []
})))
self._score_regions.append(
ba.NodeActor(
ba.newnode('region',
bs.NodeActor(
bs.newnode('region',
attrs={
'position': defs.boxes['goal2'][0:3],
'scale': defs.boxes['goal2'][6:9],
@ -288,7 +291,7 @@ class BasketGame(ba.TeamGameActivity[Player, Team]):
'materials': []
})))
self._update_scoreboard()
ba.playsound(self._chant_sound)
self._chant_sound.play()
for id, team in enumerate(self.teams):
self.postes(id)
@ -297,13 +300,13 @@ class BasketGame(ba.TeamGameActivity[Player, Team]):
self._update_scoreboard()
def _handle_ball_player_collide(self) -> None:
collision = ba.getcollision()
collision = bs.getcollision()
try:
ball = collision.sourcenode.getdelegate(Ball, True)
player = collision.opposingnode.getdelegate(PlayerSpaz,
True).getplayer(
Player, True)
except ba.NotFoundError:
except bs.NotFoundError:
return
ball.last_players_to_touch[player.team.id] = player
@ -318,7 +321,7 @@ class BasketGame(ba.TeamGameActivity[Player, Team]):
if self._ball.scored:
return
region = ba.getcollision().sourcenode
region = bs.getcollision().sourcenode
index = 0
for index in range(len(self._score_regions)):
if region == self._score_regions[index].node:
@ -334,7 +337,7 @@ class BasketGame(ba.TeamGameActivity[Player, Team]):
for player in team.players:
if player.actor:
player.actor.handlemessage(ba.CelebrateMessage(2.0))
player.actor.handlemessage(bs.CelebrateMessage(2.0))
if (scoring_team.id in self._ball.last_players_to_touch
and self._ball.last_players_to_touch[scoring_team.id]):
@ -345,28 +348,28 @@ class BasketGame(ba.TeamGameActivity[Player, Team]):
if team.score >= self._score_to_win:
self.end_game()
# ba.playsound(self._foghorn_sound)
ba.playsound(self._cheer_sound)
# self._foghorn_sound.play()
self._cheer_sound.play()
self._ball.scored = True
# Kill the ball (it'll respawn itself shortly).
ba.timer(1.0, self._kill_ball)
bs.timer(1.0, self._kill_ball)
light = ba.newnode('light',
light = bs.newnode('light',
attrs={
'position': ba.getcollision().position,
'position': bs.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)
bs.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
bs.timer(1.0, light.delete)
ba.cameraflash(duration=10.0)
bs.cameraflash(duration=10.0)
self._update_scoreboard()
def end_game(self) -> None:
results = ba.GameResults()
results = bs.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)
@ -377,7 +380,7 @@ class BasketGame(ba.TeamGameActivity[Player, Team]):
self._scoreboard.set_team_value(team, team.score, winscore)
# self.postes(id)
def spawn_player(self, player: Player) -> ba.Actor:
def spawn_player(self, player: Player) -> bs.Actor:
if bsuSpaz is None:
spaz = self.spawn_player_spaz(player)
else:
@ -390,12 +393,12 @@ class BasketGame(ba.TeamGameActivity[Player, Team]):
return spaz
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.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)
bs.timer(3.0, self._spawn_ball)
else:
super().handlemessage(msg)
@ -407,24 +410,24 @@ class BasketGame(ba.TeamGameActivity[Player, Team]):
str(team_id)]).autoretain())
def _flash_ball_spawn(self) -> None:
light = ba.newnode('light',
light = bs.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)
bs.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True)
bs.timer(1.0, light.delete)
def _spawn_ball(self) -> None:
ba.playsound(self._swipsound)
ba.playsound(self._whistle_sound)
self._swipsound.play()
self._whistle_sound.play()
self._flash_ball_spawn()
assert self._ball_spawn_pos is not None
self._ball = Ball(position=self._ball_spawn_pos)
class Aro(ba.Actor):
class Aro(bs.Actor):
def __init__(self, team: int = 0,
position: Sequence[float] = (0.0, 1.0, 0.0)):
super().__init__()
@ -434,16 +437,16 @@ class Aro(ba.Actor):
setattr(self, 'locs', [])
# Material Para; Traspasar Objetos
self.no_collision = ba.Material()
self.no_collision = bs.Material()
self.no_collision.add_actions(
actions=(('modify_part_collision', 'collide', False)))
self.collision = ba.Material()
self.collision = bs.Material()
self.collision.add_actions(
actions=(('modify_part_collision', 'collide', True)))
# Score
self._score_region_material = ba.Material()
self._score_region_material = bs.Material()
self._score_region_material.add_actions(
conditions=('they_have_material', act.ball_material),
actions=(('modify_part_collision', 'collide',
@ -454,14 +457,14 @@ class Aro(ba.Actor):
self._materials_region0 = [self.collision,
shared.footing_material]
model = None
tex = ba.gettexture('null')
mesh = None
tex = bs.gettexture('null')
pmats = [self.no_collision]
self.node = ba.newnode('prop',
self.node = bs.newnode('prop',
delegate=self,
attrs={
'model': model,
'mesh': mesh,
'color_texture': tex,
'body': 'box',
'reflection': 'soft',
@ -471,17 +474,17 @@ class Aro(ba.Actor):
'materials': pmats})
self.scale = scale = 1.4
ba.animate(self.node, 'model_scale', {0: 0})
bs.animate(self.node, 'mesh_scale', {0: 0})
pos = (position[0], position[1]+0.6, position[2])
self.regions: List[ba.Node] = [
ba.newnode('region',
self.regions: List[bs.Node] = [
bs.newnode('region',
attrs={'position': position,
'scale': (0.6, 0.05, 0.6),
'type': 'box',
'materials': self._materials_region0}),
ba.newnode('region',
bs.newnode('region',
attrs={'position': pos,
'scale': (0.5, 0.3, 0.9),
'type': 'box',
@ -502,7 +505,7 @@ class Aro(ba.Actor):
while locs_count > 1:
scale = (1.5 * 0.1 * locs_count) + 0.8
self.locs.append(ba.newnode('locator',
self.locs.append(bs.newnode('locator',
owner=self.node,
attrs={'shape': 'circleOutline',
'position': pos,
@ -528,14 +531,14 @@ class Aro(ba.Actor):
act._handle_score(self.team)
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
if isinstance(msg, bs.DieMessage):
if self.node.exists():
self.node.delete()
else:
super().handlemessage(msg)
class Cuadro(ba.Actor):
class Cuadro(bs.Actor):
def __init__(self, team: int = 0,
position: Sequence[float] = (0.0, 1.0, 0.0)):
super().__init__()
@ -543,19 +546,19 @@ class Cuadro(ba.Actor):
shared = SharedObjects.get()
setattr(self, 'locs', [])
self.collision = ba.Material()
self.collision = bs.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',
self.region: bs.Node = bs.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.shield = bs.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)
@ -578,7 +581,7 @@ class Cuadro(ba.Actor):
pos[2] += 0.19
self.locs.append(
ba.newnode('locator',
bs.newnode('locator',
owner=self.region,
attrs={'shape': 'circle',
'position': pos,
@ -595,14 +598,14 @@ class Cuadro(ba.Actor):
count_y -= 1
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
if isinstance(msg, bs.DieMessage):
if self.node.exists():
self.node.delete()
else:
super().handlemessage(msg)
class Palos(ba.Actor):
class Palos(bs.Actor):
def __init__(self, team: int = 0,
position: Sequence[float] = (0.0, 1.0, 0.0)):
super().__init__()
@ -613,26 +616,26 @@ class Palos(ba.Actor):
self.cua = None
# Material Para; Traspasar Objetos
self.no_collision = ba.Material()
self.no_collision = bs.Material()
self.no_collision.add_actions(
actions=(('modify_part_collision', 'collide', False)))
#
self.collision = ba.Material()
self.collision = bs.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')
mesh = bs.getmesh('flagPole')
tex = bs.gettexture('flagPoleColor')
pmats = [self.no_collision]
self.node = ba.newnode('prop',
self.node = bs.newnode('prop',
delegate=self,
attrs={
'model': model,
'mesh': mesh,
'color_texture': tex,
'body': 'puck',
'reflection': 'soft',
@ -643,9 +646,9 @@ class Palos(ba.Actor):
'materials': pmats
})
self.scale = scale = 4.0
ba.animate(self.node, 'model_scale', {0: scale})
bs.animate(self.node, 'mesh_scale', {0: scale})
self.loc = ba.newnode('locator',
self.loc = bs.newnode('locator',
owner=self.node,
attrs={'shape': 'circle',
'position': position,
@ -657,7 +660,7 @@ class Palos(ba.Actor):
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',
self.region = bs.newnode('region',
attrs={
'position': _pos,
'scale': (0.4, 8, 0.4),
@ -680,7 +683,7 @@ class Palos(ba.Actor):
self.cua = Cuadro(team, pos).autoretain()
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
if isinstance(msg, bs.DieMessage):
if self.node.exists():
self.node.delete()
else:
@ -698,7 +701,7 @@ class BasketMap(maps.FootballStadium):
def __init__(self) -> None:
super().__init__()
gnode = ba.getactivity().globalsnode
gnode = bs.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)
@ -715,21 +718,21 @@ class BasketMapV2(maps.HockeyStadium):
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.node.collision_mesh = bs.getcollisionmesh('footballStadiumCollide')
self.node.mesh = None
self.stands.mesh = 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'),
self.background = bs.newnode('terrain',
attrs={'mesh': bs.getmesh('thePadBG'),
'lighting': False,
'background': True,
'color': (1.0, 0.2, 1.0),
'color_texture': ba.gettexture('menuBG')})
'color_texture': bs.gettexture('menuBG')})
gnode = ba.getactivity().globalsnode
gnode = bs.getactivity().globalsnode
gnode.floor_reflection = True
gnode.debris_friction = 0.3
gnode.debris_kill_height = -0.3
@ -742,24 +745,24 @@ class BasketMapV2(maps.HockeyStadium):
self.is_hockey = False
##################
self.collision = ba.Material()
self.collision = bs.Material()
self.collision.add_actions(
actions=(('modify_part_collision', 'collide', True)))
self.regions: List[ba.Node] = [
ba.newnode('region',
self.regions: List[bs.Node] = [
bs.newnode('region',
attrs={'position': (12.676897048950195, 0.2997918128967285, 5.583303928375244),
'scale': (1.01, 12, 28),
'type': 'box',
'materials': [self.collision]}),
ba.newnode('region',
bs.newnode('region',
attrs={'position': (11.871315956115723, 0.29975247383117676, 5.711406707763672),
'scale': (50, 12, 0.9),
'type': 'box',
'materials': [self.collision]}),
ba.newnode('region',
bs.newnode('region',
attrs={'position': (-12.776557922363281, 0.30036890506744385, 4.96237850189209),
'scale': (1.01, 12, 28),
'type': 'box',
@ -767,5 +770,5 @@ class BasketMapV2(maps.HockeyStadium):
]
ba._map.register_map(BasketMap)
ba._map.register_map(BasketMapV2)
bs._map.register_map(BasketMap)
bs._map.register_map(BasketMapV2)

View file

@ -1,3 +1,4 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# Released under the MIT License. See LICENSE for details.
#
"""
@ -8,24 +9,24 @@ Youtube: https://www.youtube.com/c/HeySmoothy
Website: https://bombsquad-community.web.app
Github: https://github.com/bombsquad-community
"""
# ba_meta require api 7
# ba_meta require api 8
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
import _ba
import babase
import bascenev1 as bs
from bastd.gameutils import SharedObjects
from bastd.actor.playerspaz import PlayerSpaz
from bastd.game.keepaway import KeepAwayGame, FlagState, Player
from bastd.actor import spaz
from bascenev1lib.gameutils import SharedObjects
from bascenev1lib.actor.playerspaz import PlayerSpaz
from bascenev1lib.game.keepaway import KeepAwayGame, FlagState, Player
from bascenev1lib.actor import spaz
if TYPE_CHECKING:
from typing import Any, Sequence, Dict, Type, List, Optional, Union
# ba_meta export game
# ba_meta export bascenev1.GameActivity
class ChooseQueen(KeepAwayGame):
@ -33,11 +34,11 @@ class ChooseQueen(KeepAwayGame):
description = 'Carry the queen for a set length of time'
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.DualTeamSession)
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
return issubclass(sessiontype, bs.DualTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
return ['Creative Thoughts']
def get_instance_description(self) -> str | Sequence:
@ -50,13 +51,13 @@ class ChooseQueen(KeepAwayGame):
super().__init__(settings)
shared = SharedObjects.get()
self.lifts = {}
self._room_wall_material = ba.Material()
self._room_wall_material = bs.Material()
self._room_wall_material.add_actions(
actions=(
('modify_part_collision', 'collide', False),
('modify_part_collision', 'physical', False)
))
self._queen_material = ba.Material()
self._queen_material = bs.Material()
self._queen_material.add_actions(
conditions=('they_have_material', self._room_wall_material),
actions=(
@ -74,7 +75,7 @@ class ChooseQueen(KeepAwayGame):
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)
))
self._real_wall_material = ba.Material()
self._real_wall_material = bs.Material()
self._real_wall_material.add_actions(
actions=(
('modify_part_collision', 'collide', True),
@ -90,17 +91,17 @@ class ChooseQueen(KeepAwayGame):
))
def on_begin(self):
ba.getactivity().globalsnode.happy_thoughts_mode = True
bs.getactivity().globalsnode.happy_thoughts_mode = True
super().on_begin()
self.make_map()
def _spawn_flag(self) -> None:
ba.playsound(self._swipsound)
self._swipsound.play()
self._flash_flag_spawn()
assert self._flag_spawn_pos is not None
shared = SharedObjects.get()
self._flag = spaz.Spaz((0, 0, 0), character="Pixel").autoretain()
self._flag.handlemessage(ba.StandMessage((0, 14.63, -5.52), 93))
self._flag.handlemessage(bs.StandMessage((0, 14.63, -5.52), 93))
self._flag.node.hold_position_pressed = True
self._flag.node.materials = (self._queen_material, shared.object_material)
# self._flag.node.extras_material= tuple(list(self._flag.node.extras_material).append(self._queen_materia))
@ -108,7 +109,7 @@ class ChooseQueen(KeepAwayGame):
self._flag.hitpoints_max = 5000
self._flag_state = FlagState.NEW
self._flag_light = ba.newnode(
self._flag_light = bs.newnode(
'light',
owner=self._flag.node,
attrs={'intensity': 0.2, 'radius': 0.3, 'color': (0.2, 0.2, 0.2)},
@ -136,7 +137,7 @@ class ChooseQueen(KeepAwayGame):
player.actor.node.hold_node == self._flag.node
)
except Exception:
ba.print_exception('Error checking hold flag.')
babase.print_exception('Error checking hold flag.')
if holdingflag:
self._holding_players.append(player)
player.team.holdingflag = True
@ -158,43 +159,43 @@ class ChooseQueen(KeepAwayGame):
self._scoring_team = None
if self._flag_state != prevstate:
ba.playsound(self._swipsound)
self._swipsound.play()
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.PlayerDiedMessage):
# Augment standard behavior.
super().handlemessage(msg)
self.respawn_player(msg.getplayer(Player))
elif isinstance(msg, (ba.PickedUpMessage, ba.DroppedMessage)):
elif isinstance(msg, (bs.PickedUpMessage, bs.DroppedMessage)):
self._update_flag_state()
else:
super().handlemessage(msg)
def make_map(self):
shared = SharedObjects.get()
_ba.get_foreground_host_activity()._map.leftwall.materials = [
bs.get_foreground_host_activity()._map.leftwall.materials = [
shared.footing_material, self._real_wall_material]
_ba.get_foreground_host_activity()._map.rightwall.materials = [
bs.get_foreground_host_activity()._map.rightwall.materials = [
shared.footing_material, self._real_wall_material]
_ba.get_foreground_host_activity()._map.topwall.materials = [
bs.get_foreground_host_activity()._map.topwall.materials = [
shared.footing_material, self._real_wall_material]
self.floorwall1 = ba.newnode('region', attrs={'position': (-10, 5, -5.52), 'scale':
self.floorwall1 = bs.newnode('region', attrs={'position': (-10, 5, -5.52), 'scale':
(15, 0.2, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
self.floorwall2 = ba.newnode('region', attrs={'position': (10, 5, -5.52), 'scale': (
self.floorwall2 = bs.newnode('region', attrs={'position': (10, 5, -5.52), 'scale': (
15, 0.2, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
self.wall1 = ba.newnode('region', attrs={'position': (0, 11, -6.90), 'scale': (
self.wall1 = bs.newnode('region', attrs={'position': (0, 11, -6.90), 'scale': (
35.4, 20, 1), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
self.wall2 = ba.newnode('region', attrs={'position': (0, 11, -4.14), 'scale': (
self.wall2 = bs.newnode('region', attrs={'position': (0, 11, -4.14), 'scale': (
35.4, 20, 1), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.newnode('locator', attrs={'shape': 'box', 'position': (-10, 5, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (-10, 5, -5.52), 'color': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (15, 0.2, 2)})
ba.newnode('locator', attrs={'shape': 'box', 'position': (10, 5, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (10, 5, -5.52), 'color': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (15, 0.2, 2)})
self.create_static_step(0, 14.29)
@ -219,25 +220,25 @@ class ChooseQueen(KeepAwayGame):
self.create_static_step(-3, 10)
# create queen personal room
self.room_wall_left = ba.newnode('region', attrs={'position': (-3.633, 16.63, -5.52), 'scale':
self.room_wall_left = bs.newnode('region', attrs={'position': (-3.633, 16.63, -5.52), 'scale':
(2, 4, 5), 'type': 'box', 'materials': [shared.footing_material, self._room_wall_material]})
self.room_wall_right = ba.newnode('region', attrs={'position': (3.533, 16.63, -5.52), 'scale':
self.room_wall_right = bs.newnode('region', attrs={'position': (3.533, 16.63, -5.52), 'scale':
(2, 4, 5), 'type': 'box', 'materials': [shared.footing_material, self._room_wall_material]})
def create_static_step(self, x, y):
shared = SharedObjects.get()
ba.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (5.5, 0.1, 6),
bs.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (5.5, 0.1, 6),
'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.newnode('locator', attrs={'shape': 'box', 'position': (x, y, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (x, y, -5.52), 'color': (
1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (5.5, 0.1, 2)})
def create_slope(self, x, y, backslash):
shared = SharedObjects.get()
for _ in range(0, 21):
ba.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (0.2, 0.1, 6),
bs.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (0.2, 0.1, 6),
'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.newnode('locator', attrs={'shape': 'box', 'position': (x, y, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (x, y, -5.52), 'color': (
1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (0.2, 0.1, 2)})
if backslash:
x = x + 0.1
@ -291,7 +292,7 @@ class mapdefs:
0.5245740665, 0.5245740665, 0.01941146064)
class CreativeThoughts(ba.Map):
class CreativeThoughts(bs.Map):
"""Freaking map by smoothy."""
defs = mapdefs
@ -312,26 +313,26 @@ class CreativeThoughts(ba.Map):
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'model': ba.getmodel('alwaysLandLevel'),
'bottom_model': ba.getmodel('alwaysLandLevelBottom'),
'bgmodel': ba.getmodel('alwaysLandBG'),
'collide_model': ba.getcollidemodel('alwaysLandLevelCollide'),
'tex': ba.gettexture('alwaysLandLevelColor'),
'bgtex': ba.gettexture('alwaysLandBGColor'),
'vr_fill_mound_model': ba.getmodel('alwaysLandVRFillMound'),
'vr_fill_mound_tex': ba.gettexture('vrFillMound')
'mesh': bs.getmesh('alwaysLandLevel'),
'bottom_mesh': bs.getmesh('alwaysLandLevelBottom'),
'bgmesh': bs.getmesh('alwaysLandBG'),
'collision_mesh': bs.getcollisionmesh('alwaysLandLevelCollide'),
'tex': bs.gettexture('alwaysLandLevelColor'),
'bgtex': bs.gettexture('alwaysLandBGColor'),
'vr_fill_mound_mesh': bs.getmesh('alwaysLandVRFillMound'),
'vr_fill_mound_tex': bs.gettexture('vrFillMound')
}
return data
@classmethod
def get_music_type(cls) -> ba.MusicType:
return ba.MusicType.FLYING
def get_music_type(cls) -> bs.MusicType:
return bs.MusicType.FLYING
def __init__(self) -> None:
super().__init__(vr_overlay_offset=(0, -3.7, 2.5))
shared = SharedObjects.get()
self._fake_wall_material = ba.Material()
self._real_wall_material = ba.Material()
self._fake_wall_material = bs.Material()
self._real_wall_material = bs.Material()
self._fake_wall_material.add_actions(
conditions=(('they_are_younger_than', 9000), 'and',
('they_have_material', shared.player_material)),
@ -347,29 +348,29 @@ class CreativeThoughts(ba.Map):
('modify_part_collision', 'physical', True)
))
self.background = ba.newnode(
self.background = bs.newnode(
'terrain',
attrs={
'model': self.preloaddata['bgmodel'],
'mesh': self.preloaddata['bgmesh'],
'lighting': False,
'background': True,
'color_texture': ba.gettexture("rampageBGColor")
'color_texture': bs.gettexture("rampageBGColor")
})
self.leftwall = ba.newnode('region', attrs={'position': (-17.75152479, 13, -5.52), 'scale': (
self.leftwall = bs.newnode('region', attrs={'position': (-17.75152479, 13, -5.52), 'scale': (
0.1, 15.5, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
self.rightwall = ba.newnode('region', attrs={'position': (17.75, 13, -5.52), 'scale': (
self.rightwall = bs.newnode('region', attrs={'position': (17.75, 13, -5.52), 'scale': (
0.1, 15.5, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
self.topwall = ba.newnode('region', attrs={'position': (0, 21.0, -5.52), 'scale': (
self.topwall = bs.newnode('region', attrs={'position': (0, 21.0, -5.52), 'scale': (
35.4, 0.2, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.newnode('locator', attrs={'shape': 'box', 'position': (-17.75152479, 13, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (-17.75152479, 13, -5.52), 'color': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (0.1, 15.5, 2)})
ba.newnode('locator', attrs={'shape': 'box', 'position': (17.75, 13, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (17.75, 13, -5.52), 'color': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (0.1, 15.5, 2)})
ba.newnode('locator', attrs={'shape': 'box', 'position': (0, 21.0, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (0, 21.0, -5.52), 'color': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (35.4, 0.2, 2)})
gnode = ba.getactivity().globalsnode
gnode = bs.getactivity().globalsnode
gnode.happy_thoughts_mode = True
gnode.shadow_offset = (0.0, 8.0, 5.0)
gnode.tint = (1.3, 1.23, 1.0)
@ -380,9 +381,9 @@ class CreativeThoughts(ba.Map):
self.is_flying = True
# throw out some tips on flying
txt = ba.newnode('text',
txt = bs.newnode('text',
attrs={
'text': ba.Lstr(resource='pressJumpToFlyText'),
'text': babase.Lstr(resource='pressJumpToFlyText'),
'scale': 1.2,
'maxwidth': 800,
'position': (0, 200),
@ -391,7 +392,7 @@ class CreativeThoughts(ba.Map):
'h_align': 'center',
'v_attach': 'bottom'
})
cmb = ba.newnode('combine',
cmb = bs.newnode('combine',
owner=txt,
attrs={
'size': 4,
@ -399,12 +400,12 @@ class CreativeThoughts(ba.Map):
'input1': 0.9,
'input2': 0.0
})
ba.animate(cmb, 'input3', {3.0: 0, 4.0: 1, 9.0: 1, 10.0: 0})
bs.animate(cmb, 'input3', {3.0: 0, 4.0: 1, 9.0: 1, 10.0: 0})
cmb.connectattr('output', txt, 'color')
ba.timer(10.0, txt.delete)
bs.timer(10.0, txt.delete)
try:
ba._map.register_map(CreativeThoughts)
bs._map.register_map(CreativeThoughts)
except:
pass

View file

@ -1,3 +1,4 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# Released under the MIT License. See LICENSE for details.
#
"""
@ -8,22 +9,22 @@ Youtube: https://www.youtube.com/c/HeySmoothy
Website: https://bombsquad-community.web.app
Github: https://github.com/bombsquad-community
"""
# ba_meta require api 7
# ba_meta require api 8
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
import _ba
from ba._generated.enums import InputType
from bastd.actor.bomb import Blast
import babase
import bascenev1 as bs
from babase._mgen.enums import InputType
from bascenev1lib.actor.bomb import Blast
from bastd.gameutils import SharedObjects
from bastd.actor.playerspaz import PlayerSpaz, PlayerType
from bastd.game.deathmatch import DeathMatchGame, Player
from bastd.actor import spaz
from bascenev1lib.gameutils import SharedObjects
from bascenev1lib.actor.playerspaz import PlayerSpaz, PlayerT
from bascenev1lib.game.deathmatch import DeathMatchGame, Player
from bascenev1lib.actor import spaz
if TYPE_CHECKING:
from typing import Any, Sequence, Dict, Type, List, Optional, Union
@ -33,11 +34,11 @@ STORAGE_ATTR_NAME = f'_shared_{__name__}_factory'
# use drone as long as you want , unlike floater which dies after being idle.
class Drone(ba.Actor):
class Drone(bs.Actor):
def __init__(self, spaz):
super().__init__()
shared = SharedObjects.get()
self._drone_material = ba.Material()
self._drone_material = bs.Material()
self.loop_ascend = None
self.loop_descend = None
self.loop_lr = None
@ -59,45 +60,45 @@ class Drone(ba.Actor):
('they_have_material',
self._drone_material)),
actions=('modify_part_collision', 'physical', False))
self.node = ba.newnode(
self.node = bs.newnode(
'prop',
delegate=self,
owner=None,
attrs={
'position': spaz.node.position,
'model': ba.getmodel('landMine'),
'light_model': ba.getmodel('landMine'),
'mesh': bs.getmesh('landMine'),
'light_mesh': bs.getmesh('landMine'),
'body': 'landMine',
'body_scale': 1,
'model_scale': 1,
'mesh_scale': 1,
'shadow_size': 0.25,
'density': 999999,
'gravity_scale': 0.0,
'color_texture': ba.gettexture('achievementCrossHair'),
'color_texture': bs.gettexture('achievementCrossHair'),
'reflection': 'soft',
'reflection_scale': [0.25],
'materials': [shared.footing_material, self._drone_material]
})
self.grab_node = ba.newnode(
self.grab_node = bs.newnode(
'prop',
owner=self.node,
attrs={
'position': (0, 0, 0),
'body': 'sphere',
'model': None,
'mesh': None,
'color_texture': None,
'body_scale': 0.2,
'reflection': 'powerup',
'density': 999999,
'reflection_scale': [1.0],
'model_scale': 0.2,
'mesh_scale': 0.2,
'gravity_scale': 0,
'shadow_size': 0.1,
'is_area_of_interest': True,
'materials': [shared.object_material, self._drone_material]
})
self.node.connectattr('position', self.grab_node, 'position')
self._rcombine = ba.newnode('combine',
self._rcombine = bs.newnode('combine',
owner=self.node,
attrs={
'input0': self.spaz.node.position[0],
@ -119,12 +120,12 @@ class Drone(ba.Actor):
def ascend(self):
def loop():
if self.node.exists():
ba.animate(self._rcombine, 'input1', {
bs.animate(self._rcombine, 'input1', {
0: self.node.position[1],
1: self.node.position[1] + 2
})
loop()
self.loop_ascend = ba.Timer(1, loop, repeat=True)
self.loop_ascend = bs.Timer(1, loop, repeat=True)
def pause_movement(self):
self.loop_ascend = None
@ -132,12 +133,12 @@ class Drone(ba.Actor):
def decend(self):
def loop():
if self.node.exists():
ba.animate(self._rcombine, 'input1', {
bs.animate(self._rcombine, 'input1', {
0: self.node.position[1],
1: self.node.position[1] - 2
})
loop()
self.loop_ascend = ba.Timer(1, loop, repeat=True)
self.loop_ascend = bs.Timer(1, loop, repeat=True)
def pause_lr(self):
self.loop_lr = None
@ -148,7 +149,7 @@ class Drone(ba.Actor):
def left_(self, value=-1):
def loop():
if self.node.exists():
ba.animate(self._rcombine, 'input0', {
bs.animate(self._rcombine, 'input0', {
0: self.node.position[0],
1: self.node.position[0] + 2 * value
})
@ -158,12 +159,12 @@ class Drone(ba.Actor):
self.x_direction = value
self.z_direction = 0
loop()
self.loop_lr = ba.Timer(1, loop, repeat=True)
self.loop_lr = bs.Timer(1, loop, repeat=True)
def right_(self, value=1):
def loop():
if self.node.exists():
ba.animate(self._rcombine, 'input0', {
bs.animate(self._rcombine, 'input0', {
0: self.node.position[0],
1: self.node.position[0] + 2 * value
})
@ -173,12 +174,12 @@ class Drone(ba.Actor):
self.x_direction = value
self.z_direction = 0
loop()
self.loop_lr = ba.Timer(1, loop, repeat=True)
self.loop_lr = bs.Timer(1, loop, repeat=True)
def up_(self, value=1):
def loop():
if self.node.exists():
ba.animate(self._rcombine, 'input2', {
bs.animate(self._rcombine, 'input2', {
0: self.node.position[2],
1: self.node.position[2] - 2 * value
})
@ -188,12 +189,12 @@ class Drone(ba.Actor):
self.x_direction = 0
self.z_direction = - value
loop()
self.loop_ud = ba.Timer(1, loop, repeat=True)
self.loop_ud = bs.Timer(1, loop, repeat=True)
def down_(self, value=-1):
def loop():
if self.node.exists():
ba.animate(self._rcombine, 'input2', {
bs.animate(self._rcombine, 'input2', {
0: self.node.position[2],
1: self.node.position[2] - 2 * value
})
@ -203,17 +204,17 @@ class Drone(ba.Actor):
self.x_direction = 0
self.z_direction = - value
loop()
self.loop_ud = ba.Timer(1, loop, repeat=True)
self.loop_ud = bs.Timer(1, loop, repeat=True)
def handlemessage(self, msg):
if isinstance(msg, ba.DieMessage):
if isinstance(msg, bs.DieMessage):
self.node.delete()
self.grab_node.delete()
self.loop_ascend = None
self.loop_ud = None
self.loop_lr = None
elif isinstance(msg, ba.OutOfBoundsMessage):
self.handlemessage(ba.DieMessage())
elif isinstance(msg, bs.OutOfBoundsMessage):
self.handlemessage(bs.DieMessage())
else:
super().handlemessage(msg)
@ -224,7 +225,7 @@ class RocketFactory:
"""Quake Rocket factory"""
def __init__(self) -> None:
self.ball_material = ba.Material()
self.ball_material = bs.Material()
self.ball_material.add_actions(
conditions=((('we_are_younger_than', 5), 'or',
@ -251,7 +252,7 @@ class RocketFactory:
@classmethod
def get(cls):
"""Get factory if exists else create new"""
activity = ba.getactivity()
activity = bs.getactivity()
if hasattr(activity, STORAGE_ATTR_NAME):
return getattr(activity, STORAGE_ATTR_NAME)
factory = cls()
@ -263,30 +264,30 @@ class RocketLauncher:
"""Very dangerous weapon"""
def __init__(self):
self.last_shot = ba.time()
self.last_shot = bs.time()
def give(self, spaz: spaz.Spaz) -> None:
"""Give spaz a rocket launcher"""
spaz.punch_callback = self.shot
self.last_shot = ba.time()
self.last_shot = bs.time()
# FIXME
# noinspection PyUnresolvedReferences
def shot(self, spaz, x, z, position) -> None:
"""Release a rocket"""
time = ba.time()
time = bs.time()
if time - self.last_shot > 0.6:
self.last_shot = time
direction = [x, 0, z]
direction[1] = 0.0
mag = 10.0 / 1 if ba.Vec3(*direction).length() == 0 else ba.Vec3(*direction).length()
mag = 10.0 / 1 if babase.Vec3(*direction).length() == 0 else babase.Vec3(*direction).length()
vel = [v * mag for v in direction]
Rocket(position=position,
velocity=vel,
owner=spaz.getplayer(ba.Player),
source_player=spaz.getplayer(ba.Player),
owner=spaz.getplayer(bs.Player),
source_player=spaz.getplayer(bs.Player),
color=spaz.node.color).autoretain()
@ -294,7 +295,7 @@ class ImpactMessage:
"""Rocket touched something"""
class Rocket(ba.Actor):
class Rocket(bs.Actor):
"""Epic rocket from rocket launcher"""
def __init__(self,
@ -309,16 +310,16 @@ class Rocket(ba.Actor):
self._color = color
factory = RocketFactory.get()
self.node = ba.newnode('prop',
self.node = bs.newnode('prop',
delegate=self,
attrs={
'position': position,
'velocity': velocity,
'model': ba.getmodel('impactBomb'),
'mesh': bs.getmesh('impactBomb'),
'body': 'sphere',
'color_texture': ba.gettexture(
'color_texture': bs.gettexture(
'bunnyColor'),
'model_scale': 0.2,
'mesh_scale': 0.2,
'is_area_of_interest': True,
'body_scale': 0.8,
'materials': [
@ -328,17 +329,17 @@ class Rocket(ba.Actor):
self.node.extra_acceleration = (self.node.velocity[0] * 200, 0,
self.node.velocity[2] * 200)
self._life_timer = ba.Timer(
5, ba.WeakCall(self.handlemessage, ba.DieMessage()))
self._life_timer = bs.Timer(
5, bs.WeakCall(self.handlemessage, bs.DieMessage()))
self._emit_timer = ba.Timer(0.001, ba.WeakCall(self.emit), repeat=True)
self._emit_timer = bs.Timer(0.001, bs.WeakCall(self.emit), repeat=True)
self.base_pos_y = self.node.position[1]
ba.camerashake(5.0)
bs.camerashake(5.0)
def emit(self) -> None:
"""Emit a trace after rocket"""
ba.emitfx(position=self.node.position,
bs.emitfx(position=self.node.position,
scale=0.4,
spread=0.01,
chunk_type='spark')
@ -346,7 +347,7 @@ class Rocket(ba.Actor):
return
self.node.position = (self.node.position[0], self.base_pos_y,
self.node.position[2]) # ignore y
ba.newnode('explosion',
bs.newnode('explosion',
owner=self.node,
attrs={
'position': self.node.position,
@ -358,9 +359,9 @@ class Rocket(ba.Actor):
"""Message handling for rocket"""
super().handlemessage(msg)
if isinstance(msg, ImpactMessage):
self.node.handlemessage(ba.DieMessage())
self.node.handlemessage(bs.DieMessage())
elif isinstance(msg, ba.DieMessage):
elif isinstance(msg, bs.DieMessage):
if self.node:
Blast(position=self.node.position,
blast_radius=2,
@ -369,25 +370,25 @@ class Rocket(ba.Actor):
self.node.delete()
self._emit_timer = None
elif isinstance(msg, ba.OutOfBoundsMessage):
self.handlemessage(ba.DieMessage())
elif isinstance(msg, bs.OutOfBoundsMessage):
self.handlemessage(bs.DieMessage())
# ba_meta export game
# ba_meta export bascenev1.GameActivity
class ChooseQueen(DeathMatchGame):
name = 'Drone War'
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.DualTeamSession)
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
return issubclass(sessiontype, bs.DualTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
return ['Football Stadium']
def spawn_player_spaz(
self,
player: PlayerType,
player: PlayerT,
position: Sequence[float] | None = None,
angle: float | None = None,
) -> PlayerSpaz:
@ -398,29 +399,29 @@ class ChooseQueen(DeathMatchGame):
def on_begin(self):
super().on_begin()
shared = SharedObjects.get()
self.ground_material = ba.Material()
self.ground_material = bs.Material()
self.ground_material.add_actions(
conditions=('they_have_material', shared.player_material),
actions=(
('modify_part_collision', 'collide', True),
('call', 'at_connect', ba.Call(self._handle_player_collide)),
('call', 'at_connect', babase.Call(self._handle_player_collide)),
),
)
pos = (0, 0.1, -5)
self.main_region = ba.newnode('region', attrs={'position': pos, 'scale': (
self.main_region = bs.newnode('region', attrs={'position': pos, 'scale': (
30, 0.001, 23), 'type': 'box', 'materials': [shared.footing_material, self.ground_material]})
def _handle_player_collide(self):
try:
player = ba.getcollision().opposingnode.getdelegate(
player = bs.getcollision().opposingnode.getdelegate(
PlayerSpaz, True)
except ba.NotFoundError:
except bs.NotFoundError:
return
if player.is_alive():
player.shatter(True)
def spawn_drone(self, spaz):
with ba.Context(_ba.get_foreground_host_activity()):
with bs.get_foreground_host_activity().context:
drone = Drone(spaz)
r_launcher = RocketLauncher()

View file

@ -1,3 +1,4 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
"""
Hot Potato by TheMikirog#1984
@ -13,20 +14,23 @@
"""
# ba_meta require api 7
# ba_meta require api 8
from __future__ import annotations
from typing import TYPE_CHECKING
# Define only what we need and nothing more
import ba
from bastd.actor.spaz import SpazFactory
from bastd.actor.spaz import PickupMessage
from bastd.actor.spaz import BombDiedMessage
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.bomb import Bomb
from bastd.actor.bomb import Blast
from baenv import TARGET_BALLISTICA_BUILD as build_number
import babase
import bauiv1 as bui
import bascenev1 as bs
from bascenev1lib.actor.spaz import SpazFactory
from bascenev1lib.actor.spaz import PickupMessage
from bascenev1lib.actor.spaz import BombDiedMessage
from bascenev1lib.actor.playerspaz import PlayerSpaz
from bascenev1lib.actor.bomb import Bomb
from bascenev1lib.actor.bomb import Blast
from enum import Enum
import random
@ -72,7 +76,7 @@ class PlayerState(Enum):
# Here's the behavior of each icon.
class Icon(ba.Actor):
class Icon(bs.Actor):
"""Creates in in-game icon on screen."""
def __init__(self,
@ -88,11 +92,11 @@ class Icon(ba.Actor):
self._player = player
self._name_scale = name_scale
self._outline_tex = ba.gettexture('characterIconMask')
self._outline_tex = bui.gettexture('characterIconMask')
# Character portrait
icon = player.get_icon()
self.node = ba.newnode('image',
self.node = bs.newnode('image',
delegate=self,
attrs={
'texture': icon['texture'],
@ -106,12 +110,12 @@ class Icon(ba.Actor):
'attach': 'bottomCenter'
})
# Player name
self._name_text = ba.newnode(
self._name_text = bs.newnode(
'text',
owner=self.node,
attrs={
'text': ba.Lstr(value=player.getname()),
'color': ba.safecolor(player.team.color),
'text': babase.Lstr(value=player.getname()),
'color': babase.safecolor(player.team.color),
'h_align': 'center',
'v_align': 'center',
'vr_depth': 410,
@ -122,7 +126,7 @@ class Icon(ba.Actor):
'v_attach': 'bottom'
})
# Status text (such as Marked!, Stunned! and You're Out!)
self._marked_text = ba.newnode(
self._marked_text = bs.newnode(
'text',
owner=self.node,
attrs={
@ -137,11 +141,11 @@ class Icon(ba.Actor):
'v_attach': 'bottom'
})
# Status icon overlaying the character portrait
self._marked_icon = ba.newnode(
self._marked_icon = bs.newnode(
'text',
owner=self.node,
attrs={
'text': ba.charstr(ba.SpecialChar.HAL),
'text': babase.charstr(babase.SpecialChar.HAL),
'color': (1, 1, 1),
'h_align': 'center',
'v_align': 'center',
@ -169,7 +173,7 @@ class Icon(ba.Actor):
self.node.color = (1.0, 1.0, 1.0)
# Marked players get ALL of the attention - red portrait, red text and icon overlaying the portrait
elif type is PlayerState.MARKED:
self._marked_icon.text = ba.charstr(ba.SpecialChar.HAL)
self._marked_icon.text = babase.charstr(babase.SpecialChar.HAL)
self._marked_icon.position = (pos[0] - 1, pos[1] - 13)
self._marked_icon.opacity = 1.0
self._marked_text.text = 'Marked!'
@ -179,7 +183,7 @@ class Icon(ba.Actor):
self.node.color = (1.0, 0.2, 0.2)
# Stunned players are just as important - yellow portrait, yellow text and moon icon.
elif type is PlayerState.STUNNED:
self._marked_icon.text = ba.charstr(ba.SpecialChar.MOON)
self._marked_icon.text = babase.charstr(babase.SpecialChar.MOON)
self._marked_icon.position = (pos[0] - 2, pos[1] - 12)
self._marked_icon.opacity = 1.0
self._marked_text.text = 'Stunned!'
@ -189,17 +193,17 @@ class Icon(ba.Actor):
# Eliminated players get special treatment.
# We make the portrait semi-transparent, while adding some visual flair with an fading skull icon and text.
elif type is PlayerState.ELIMINATED:
self._marked_icon.text = ba.charstr(ba.SpecialChar.SKULL)
self._marked_icon.text = babase.charstr(babase.SpecialChar.SKULL)
self._marked_icon.position = (pos[0] - 2, pos[1] - 12)
self._marked_text.text = 'You\'re Out!'
self._marked_text.color = (0.5, 0.5, 0.5)
# Animate text and icon
animation_end_time = 1.5 if bool(self.activity.settings['Epic Mode']) else 3.0
ba.animate(self._marked_icon, 'opacity', {
bs.animate(self._marked_icon, 'opacity', {
0: 1.0,
animation_end_time: 0.0})
ba.animate(self._marked_text, 'opacity', {
bs.animate(self._marked_text, 'opacity', {
0: 1.0,
animation_end_time: 0.0})
@ -235,7 +239,7 @@ class PotatoPlayerSpaz(PlayerSpaz):
self.dropped_bombs = [] # we use this to track bombs thrown by the player
# Define a marked light
self.marked_light = ba.newnode('light',
self.marked_light = bs.newnode('light',
owner=self.node,
attrs={'position': self.node.position,
'radius': 0.15,
@ -244,7 +248,7 @@ class PotatoPlayerSpaz(PlayerSpaz):
'color': (1.0, 0.0, 0.0)})
# Pulsing red light when the player is Marked
ba.animate(self.marked_light, 'radius', {
bs.animate(self.marked_light, 'radius', {
0: 0.1,
0.3: 0.15,
0.6: 0.1},
@ -252,12 +256,12 @@ class PotatoPlayerSpaz(PlayerSpaz):
self.node.connectattr('position_center', self.marked_light, 'position')
# Marked timer. It should be above our head, so we attach the text to the offset that's attached to the player.
self.marked_timer_offset = ba.newnode('math', owner=self.node, attrs={
self.marked_timer_offset = bs.newnode('math', owner=self.node, attrs={
'input1': (0, 1.2, 0),
'operation': 'add'})
self.node.connectattr('torso_position', self.marked_timer_offset, 'input2')
self.marked_timer_text = ba.newnode('text', owner=self.node, attrs={
self.marked_timer_text = bs.newnode('text', owner=self.node, attrs={
'text': '',
'in_world': True,
'shadow': 0.4,
@ -278,7 +282,7 @@ class PotatoPlayerSpaz(PlayerSpaz):
# Add our bomb to the list of our tracked bombs
self.dropped_bombs.append(bomb)
# Bring a light
bomb.bomb_marked_light = ba.newnode('light',
bomb.bomb_marked_light = bs.newnode('light',
owner=bomb.node,
attrs={'position': bomb.node.position,
'radius': 0.04,
@ -291,7 +295,7 @@ class PotatoPlayerSpaz(PlayerSpaz):
self.set_bombs_marked()
# When the bomb physics node dies, call a function.
bomb.node.add_death_action(
ba.WeakCall(self.bomb_died, bomb))
bs.WeakCall(self.bomb_died, bomb))
# Here's the function that gets called when one of the player's bombs dies.
# We reference the player's dropped_bombs list and remove the bomb that died.
@ -309,7 +313,7 @@ class PotatoPlayerSpaz(PlayerSpaz):
# Since our gamemode relies heavily on players passing the mark to other players
# we need to have access to this message. This gets called when the player takes damage for any reason.
def handlemessage(self, msg):
if isinstance(msg, ba.HitMessage):
if isinstance(msg, bs.HitMessage):
# This is basically the same HitMessage code as in the original Spaz.
# The only difference is that there is no health bar and you can't die with punches or bombs.
# Also some useless or redundant code was removed.
@ -326,9 +330,7 @@ class PotatoPlayerSpaz(PlayerSpaz):
# If the attacker is healthy and we're stunned, do a flash and play a sound, then ignore the rest of the code.
if self.source_player.state == PlayerState.STUNNED and msg._source_player != PlayerState.MARKED:
self.node.handlemessage('flash')
ba.playsound(SpazFactory.get().block_sound,
1.0,
position=self.node.position)
SpazFactory.get().block_sound.play(1.0, position=self.node.position)
return True
# Here's all the damage and force calculations unchanged from the source.
@ -360,11 +362,11 @@ class PotatoPlayerSpaz(PlayerSpaz):
sound = SpazFactory.get().punch_sound
else:
sound = SpazFactory.get().punch_sound_weak
ba.playsound(sound, 1.0, position=self.node.position)
sound.play(1.0, position=self.node.position)
# Throw up some chunks.
assert msg.force_direction is not None
ba.emitfx(position=msg.pos,
bs.emitfx(position=msg.pos,
velocity=(msg.force_direction[0] * 0.5,
msg.force_direction[1] * 0.5,
msg.force_direction[2] * 0.5),
@ -372,7 +374,7 @@ class PotatoPlayerSpaz(PlayerSpaz):
scale=0.3,
spread=0.03)
ba.emitfx(position=msg.pos,
bs.emitfx(position=msg.pos,
chunk_type='sweat',
velocity=(msg.force_direction[0] * 1.3,
msg.force_direction[1] * 1.3 + 5.0,
@ -387,7 +389,7 @@ class PotatoPlayerSpaz(PlayerSpaz):
msg.pos[1] + msg.force_direction[1] * 0.02,
msg.pos[2] + msg.force_direction[2] * 0.02)
flash_color = (1.0, 0.8, 0.4)
light = ba.newnode(
light = bs.newnode(
'light',
attrs={
'position': punchpos,
@ -396,20 +398,20 @@ class PotatoPlayerSpaz(PlayerSpaz):
'height_attenuated': False,
'color': flash_color
})
ba.timer(0.06, light.delete)
bs.timer(0.06, light.delete)
flash = ba.newnode('flash',
flash = bs.newnode('flash',
attrs={
'position': punchpos,
'size': 0.17 + 0.17 * hurtiness,
'color': flash_color
})
ba.timer(0.06, flash.delete)
bs.timer(0.06, flash.delete)
# Physics collision particles.
if msg.hit_type == 'impact':
assert msg.force_direction is not None
ba.emitfx(position=msg.pos,
bs.emitfx(position=msg.pos,
velocity=(msg.force_direction[0] * 2.0,
msg.force_direction[1] * 2.0,
msg.force_direction[2] * 2.0),
@ -435,9 +437,9 @@ class PotatoPlayerSpaz(PlayerSpaz):
# Let's get all collision data if we can. Otherwise cancel.
try:
collision = ba.getcollision()
collision = bs.getcollision()
opposingnode = collision.opposingnode
except ba.NotFoundError:
except bs.NotFoundError:
return True
# Our grabber needs to be a Spaz
@ -447,9 +449,7 @@ class PotatoPlayerSpaz(PlayerSpaz):
# It's the same sound and flashing behavior as hitting a stunned player as a healthy player.
if (opposingnode.source_player.state == PlayerState.STUNNED and self.source_player.state != PlayerState.MARKED):
opposingnode.handlemessage('flash')
ba.playsound(SpazFactory.get().block_sound,
1.0,
position=opposingnode.position)
SpazFactory.get().block_sound.play(1.0, position=opposingnode.position)
return True
# If they're marked and we're healthy or stunned, pass that mark along to us.
elif opposingnode.source_player.state in [PlayerState.REGULAR, PlayerState.STUNNED] and self.source_player.state == PlayerState.MARKED:
@ -458,10 +458,10 @@ class PotatoPlayerSpaz(PlayerSpaz):
# Our work is done. Continue with the rest of the grabbing behavior as usual.
super().handlemessage(msg)
# Dying is important in this gamemode and as such we need to address this behavior.
elif isinstance(msg, ba.DieMessage):
elif isinstance(msg, bs.DieMessage):
# If a player left the game, inform our gamemode logic.
if msg.how == ba.DeathType.LEFT_GAME:
if msg.how == bs.DeathType.LEFT_GAME:
self.activity.player_left(self.source_player)
# If a MARKED or STUNNED player dies, hide the text from the previous spaz.
@ -470,7 +470,7 @@ class PotatoPlayerSpaz(PlayerSpaz):
self.marked_timer_text.color[1],
self.marked_timer_text.color[2],
0.0)
ba.animate(self.marked_light, 'intensity', {
bs.animate(self.marked_light, 'intensity', {
0: self.marked_light.intensity,
0.5: 0.0})
@ -483,7 +483,7 @@ class PotatoPlayerSpaz(PlayerSpaz):
# A concept of a player is very useful to reference if we don't have a player character present (maybe they died).
class Player(ba.Player['Team']):
class Player(bs.Player['Team']):
"""Our player type for this game."""
def __init__(self) -> None:
@ -535,8 +535,8 @@ class Player(ba.Player['Team']):
self.stunned_time_remaining = stun_time # Set our stun time remaining
# Remove our stun once the time is up
self.stunned_timer = ba.Timer(stun_time + 0.1, ba.Call(self.stun_remove))
self.stunned_update_timer = ba.Timer(0.1, ba.Call(
self.stunned_timer = bs.Timer(stun_time + 0.1, babase.Call(self.stun_remove))
self.stunned_update_timer = bs.Timer(0.1, babase.Call(
self.stunned_timer_tick), repeat=True) # Call a function every 0.1 seconds
self.fall_times += 1 # Increase the amount of times we fell by one
# Change the text above the Spaz's head to total stun time
@ -579,8 +579,8 @@ class Player(ba.Player['Team']):
self.icon.set_marked_icon(state) # Update our icon
# ba_meta export game
class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
# ba_meta export bascenev1.GameActivity
class HotPotato(bs.TeamGameActivity[Player, bs.Team]):
# Let's define the basics like the name of the game, description and some tips that should appear at the start of a match.
name = 'Hot Potato'
@ -604,8 +604,8 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
# We're gonna distribute end of match session scores based on who dies first and who survives.
# First place gets most points, then second, then third.
scoreconfig = ba.ScoreConfig(label='Place',
scoretype=ba.ScoreType.POINTS,
scoreconfig = bs.ScoreConfig(label='Place',
scoretype=bs.ScoreType.POINTS,
lower_is_better=True)
# These variables are self explanatory too.
@ -614,25 +614,25 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
# Let's define some settings the user can mess around with to fit their needs.
available_settings = [
ba.IntSetting('Elimination Timer',
bs.IntSetting('Elimination Timer',
min_value=5,
default=15,
increment=1,
),
ba.BoolSetting('Marked Players use Impact Bombs', default=False),
ba.BoolSetting('Epic Mode', default=False),
bs.BoolSetting('Marked Players use Impact Bombs', default=False),
bs.BoolSetting('Epic Mode', default=False),
]
# Hot Potato is strictly a Free-For-All gamemode, so only picking the gamemode in FFA playlists.
@classmethod
def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.FreeForAllSession)
def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
return issubclass(sessiontype, bs.FreeForAllSession)
# Most maps should work in Hot Potato. Generally maps marked as 'melee' are the most versatile map types of them all.
# As the name implies, fisticuffs are common forms of engagement.
@classmethod
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
return ba.getmaps('melee')
def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
return bs.app.classic.getmaps('melee')
# Here we define everything the gamemode needs, like sounds and settings.
def __init__(self, settings: dict):
@ -640,22 +640,22 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
self.settings = settings
# Let's define all of the sounds we need.
self._tick_sound = ba.getsound('tick')
self._player_eliminated_sound = ba.getsound('playerDeath')
self._tick_sound = bui.getsound('tick')
self._player_eliminated_sound = bui.getsound('playerDeath')
# These next sounds are arrays instead of single sounds.
# We'll use that fact later.
self._danger_tick_sounds = [ba.getsound('orchestraHit'),
ba.getsound('orchestraHit2'),
ba.getsound('orchestraHit3')]
self._marked_sounds = [ba.getsound('powerdown01'),
ba.getsound('activateBeep'),
ba.getsound('hiss')]
self._danger_tick_sounds = [bui.getsound('orchestraHit'),
bui.getsound('orchestraHit2'),
bui.getsound('orchestraHit3')]
self._marked_sounds = [bui.getsound('powerdown01'),
bui.getsound('activateBeep'),
bui.getsound('hiss')]
# Normally play KOTH music, but switch to Epic music if we're in slow motion.
self._epic_mode = bool(settings['Epic Mode'])
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
ba.MusicType.SCARY)
self.default_music = (bs.MusicType.EPIC if self._epic_mode else
bs.MusicType.SCARY)
# This description appears below the title card after it comes crashing when the game begins.
def get_instance_description(self) -> str | Sequence:
@ -680,7 +680,7 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
# Returns every single marked player.
# This piece of info is used excensively in this gamemode, so it's advantageous to have a function to cut on
# work and make the gamemode easier to maintain
def get_marked_players(self) -> Sequence[ba.Player]:
def get_marked_players(self) -> Sequence[bs.Player]:
marked_players = []
for p in self.players:
if p.state == PlayerState.MARKED:
@ -691,7 +691,7 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
def mark(self, target: Player) -> None:
target.set_state(PlayerState.MARKED)
ba.emitfx(position=target.actor.node.position,
bs.emitfx(position=target.actor.node.position,
velocity=target.actor.node.velocity,
chunk_type='spark',
count=int(20.0+random.random()*20),
@ -738,7 +738,7 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
sound_volume = 1.0 / marked_player_amount
for target in marked_players:
ba.playsound(self._tick_sound, sound_volume, target.actor.node.position)
self._tick_sound.play(sound_volume, target.actor.node.position)
target.actor.marked_timer_text.text = str(self.elimination_timer_display)
# When counting down 3, 2, 1 play some dramatic sounds
@ -746,7 +746,7 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
# We store our dramatic sounds in an array, so we target a specific element on the array
# depending on time remaining. Arrays start at index 0, so we need to decrease
# our variable by 1 to get the element index.
ba.playsound(self._danger_tick_sounds[self.elimination_timer_display - 1], 1.5)
self._danger_tick_sounds[self.elimination_timer_display - 1].play(1.5)
else:
# Elimination timer is up! Let's eliminate all marked players.
self.elimination_timer_display -= 1 # Decrease our timer by one second.
@ -763,18 +763,18 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
velocity=target.actor.node.velocity,
blast_radius=3.0,
source_player=target).autoretain()
ba.emitfx(position=target.actor.node.position,
bs.emitfx(position=target.actor.node.position,
velocity=target.actor.node.velocity,
count=int(16.0+random.random()*60),
scale=1.5,
spread=2,
chunk_type='spark')
target.actor.handlemessage(ba.DieMessage(how='marked_elimination'))
target.actor.handlemessage(bs.DieMessage(how='marked_elimination'))
target.actor.shatter(extreme=True)
self.match_placement.append(target.team)
ba.playsound(self._player_eliminated_sound, 1.0)
self._player_eliminated_sound.play(1.0)
# Let the gamemode know a Marked
self.marked_players_died()
@ -788,13 +788,13 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
# Let's add our lone survivor to the match placement list.
self.match_placement.append(alive_players[0].team)
# Wait a while to let this sink in before we announce our victor.
self._end_game_timer = ba.Timer(1.25, ba.Call(self.end_game))
self._end_game_timer = bs.Timer(1.25, babase.Call(self.end_game))
else:
# There's still players remaining, so let's wait a while before marking a new player.
self.new_mark_timer = ba.Timer(2.0 if self.slow_motion else 4.0, ba.Call(self.new_mark))
self.new_mark_timer = bs.Timer(2.0 if self.slow_motion else 4.0, babase.Call(self.new_mark))
# Another extensively used function that returns all alive players.
def get_alive_players(self) -> Sequence[ba.Player]:
def get_alive_players(self) -> Sequence[bs.Player]:
alive_players = []
for player in self.players:
if player.state == PlayerState.ELIMINATED:
@ -829,14 +829,14 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
# Set time until marked players explode
self.elimination_timer_display = self.settings['Elimination Timer']
# Set a timer that calls _eliminate_tick every second
self.marked_tick_timer = ba.Timer(1.0, ba.Call(self._eliminate_tick), repeat=True)
self.marked_tick_timer = bs.Timer(1.0, babase.Call(self._eliminate_tick), repeat=True)
# Mark all chosen victims and play a sound
for new_victim in all_victims:
# _marked_sounds is an array.
# To make a nice marked sound effect, I play multiple sounds at once
# All of them are contained in the array.
for sound in self._marked_sounds:
ba.playsound(sound, 1.0, new_victim.actor.node.position)
sound.play(1.0, new_victim.actor.node.position)
self.mark(new_victim)
# This function is called when the gamemode first loads.
@ -849,10 +849,10 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
# End the game if there's only one player
if len(self.players) < 2:
self.match_placement.append(self.players[0].team)
self._round_end_timer = ba.Timer(0.5, self.end_game)
self._round_end_timer = bs.Timer(0.5, self.end_game)
else:
# Pick random player(s) to get marked
self.new_mark_timer = ba.Timer(2.0 if self.slow_motion else 5.2, ba.Call(self.new_mark))
self.new_mark_timer = bs.Timer(2.0 if self.slow_motion else 5.2, babase.Call(self.new_mark))
self._update_icons() # Create player state icons
@ -873,17 +873,17 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
# I'm gonna modify this function to move the tip text above the icons.
def _show_tip(self) -> None:
from ba._gameutils import animate, GameTip
from ba._generated.enums import SpecialChar
from ba._language import Lstr
from bascenev1._gameutils import animate, GameTip
from babase._mgen.enums import SpecialChar
from babase._language import Lstr
# If there's any tips left on the list, display one.
if self.tips:
tip = self.tips.pop(random.randrange(len(self.tips)))
tip_title = Lstr(value='${A}:',
subs=[('${A}', Lstr(resource='tipText'))])
icon: ba.Texture | None = None
sound: ba.Sound | None = None
icon: babase.Texture | None = None
sound: babase.Sound | None = None
if isinstance(tip, GameTip):
icon = tip.icon
sound = tip.sound
@ -893,15 +893,15 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
# Do a few replacements.
tip_lstr = Lstr(translate=('tips', tip),
subs=[('${PICKUP}',
ba.charstr(SpecialChar.TOP_BUTTON))])
babase.charstr(SpecialChar.TOP_BUTTON))])
base_position = (75, 50)
tip_scale = 0.8
tip_title_scale = 1.2
vrmode = ba.app.vr_mode
vrmode = babase.app.vr_mode if build_number < 21282 else babase.app.env.vr
t_offs = -350.0
height_offs = 100.0
tnode = ba.newnode('text',
tnode = bs.newnode('text',
attrs={
'text': tip_lstr,
'scale': tip_scale,
@ -917,7 +917,7 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
})
t2pos = (base_position[0] + t_offs - (20 if icon is None else 82),
base_position[1] + 2 + height_offs)
t2node = ba.newnode('text',
t2node = bs.newnode('text',
owner=tnode,
attrs={
'text': tip_title,
@ -933,7 +933,7 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
})
if icon is not None:
ipos = (base_position[0] + t_offs - 40, base_position[1] + 1 + height_offs)
img = ba.newnode('image',
img = bs.newnode('image',
attrs={
'texture': icon,
'position': ipos,
@ -945,11 +945,11 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
'attach': 'bottomCenter'
})
animate(img, 'opacity', {0: 0, 1.0: 1, 4.0: 1, 5.0: 0})
ba.timer(5.0, img.delete)
bs.timer(5.0, img.delete)
if sound is not None:
ba.playsound(sound)
sound.play()
combine = ba.newnode('combine',
combine = bs.newnode('combine',
owner=tnode,
attrs={
'input0': 1.0,
@ -960,7 +960,7 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
combine.connectattr('output', tnode, 'color')
combine.connectattr('output', t2node, 'color')
animate(combine, 'input3', {0: 0, 1.0: 1, 4.0: 1, 5.0: 0})
ba.timer(5.0, tnode.delete)
bs.timer(5.0, tnode.delete)
# This function is called when a player leaves the game.
# This is only called when the player already joined with a character.
@ -985,7 +985,7 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
player.set_state(PlayerState.ELIMINATED)
# This function is called every time a player spawns
def spawn_player(self, player: Player) -> ba.Actor:
def spawn_player(self, player: Player) -> bs.Actor:
position = self.map.get_ffa_start_position(self.players)
position = (position[0],
position[1] - 0.3, # Move the spawn a bit lower
@ -993,8 +993,8 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
name = player.getname()
light_color = ba.normalized_color(player.color)
display_color = ba.safecolor(player.color, target_intensity=0.75)
light_color = babase.normalized_color(player.color)
display_color = babase.safecolor(player.color, target_intensity=0.75)
# Here we actually crate the player character
spaz = PotatoPlayerSpaz(color=player.color,
@ -1009,20 +1009,20 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
spaz.connect_controls_to_player()
# Move to the stand position and add a flash of light
spaz.handlemessage(ba.StandMessage(position, random.uniform(0, 360)))
t = ba.time(ba.TimeType.BASE)
ba.playsound(self._spawn_sound, 1.0, position=spaz.node.position)
light = ba.newnode('light', attrs={'color': light_color})
spaz.handlemessage(bs.StandMessage(position, random.uniform(0, 360)))
t = bs.time()
self._spawn_sound.play(1.0, position=spaz.node.position)
light = bs.newnode('light', attrs={'color': light_color})
spaz.node.connectattr('position', light, 'position')
ba.animate(light, 'intensity', {0: 0,
bs.animate(light, 'intensity', {0: 0,
0.25: 1,
0.5: 0})
ba.timer(0.5, light.delete)
bs.timer(0.5, light.delete)
# Game reacts to various events
def handlemessage(self, msg: Any) -> Any:
# This is called if the player dies.
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.PlayerDiedMessage):
super().handlemessage(msg)
player = msg.getplayer(Player)
@ -1046,7 +1046,7 @@ class HotPotato(ba.TeamGameActivity[Player, ba.Team]):
# Proceed only if the game hasn't ended yet.
if self.has_ended():
return
results = ba.GameResults()
results = bs.GameResults()
# By this point our match placement list should be filled with all players.
# Players that died/left earliest should be the first entries.
# We're gonna use array indexes to decide match placements.

View file

@ -1,3 +1,4 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# Released under the MIT License. See LICENSE for details.
#
# By itsre3
@ -6,39 +7,41 @@
# Besides that, enjoy.......!!
"""Provides the chosen-one mini-game."""
# ba_meta require api 7
# ba_meta require api 8
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
from bastd.actor.flag import Flag
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
from bastd.gameutils import SharedObjects
import babase
import bauiv1 as bui
import bascenev1 as bs
from bascenev1lib.actor.flag import Flag
from bascenev1lib.actor.playerspaz import PlayerSpaz
from bascenev1lib.actor.scoreboard import Scoreboard
from bascenev1lib.gameutils import SharedObjects
if TYPE_CHECKING:
from typing import Any, Type, List, Dict, Optional, Sequence, Union
class Player(ba.Player['Team']):
class Player(bs.Player['Team']):
"""Our player type for this game."""
def __init__(self) -> None:
self.chosen_light: Optional[ba.NodeActor] = None
self.chosen_light: Optional[bs.NodeActor] = None
class Team(ba.Team[Player]):
class Team(bs.Team[Player]):
"""Our team type for this game."""
def __init__(self, time_remaining: int) -> None:
self.time_remaining = time_remaining
# ba_meta export game
class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
# ba_meta export bascenev1.GameActivity
class InvicibleOneGame(bs.TeamGameActivity[Player, Team]):
"""
Game involving trying to remain the one 'invisible one'
for a set length of time while everyone else tries to
@ -49,15 +52,15 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
description = ('Be the invisible one for a length of time to win.\n'
'Kill the invisible one to become it.')
available_settings = [
ba.IntSetting(
bs.IntSetting(
'Invicible One Time',
min_value=10,
default=30,
increment=10,
),
ba.BoolSetting('Invicible one is lazy', default=True),
ba.BoolSetting('Night mode', default=False),
ba.IntChoiceSetting(
bs.BoolSetting('Invicible one is lazy', default=True),
bs.BoolSetting('Night mode', default=False),
bs.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
@ -69,7 +72,7 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
],
default=0,
),
ba.FloatChoiceSetting(
bs.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
@ -80,35 +83,35 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
],
default=1.0,
),
ba.BoolSetting('Epic Mode', default=False),
bs.BoolSetting('Epic Mode', default=False),
]
scoreconfig = ba.ScoreConfig(label='Time Held')
scoreconfig = bs.ScoreConfig(label='Time Held')
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ba.getmaps('keep_away')
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
return bs.app.classic.getmaps('keep_away')
def __init__(self, settings: dict):
super().__init__(settings)
self._scoreboard = Scoreboard()
self._invicible_one_player: Optional[Player] = None
self._swipsound = ba.getsound('swip')
self._countdownsounds: Dict[int, ba.Sound] = {
10: ba.getsound('announceTen'),
9: ba.getsound('announceNine'),
8: ba.getsound('announceEight'),
7: ba.getsound('announceSeven'),
6: ba.getsound('announceSix'),
5: ba.getsound('announceFive'),
4: ba.getsound('announceFour'),
3: ba.getsound('announceThree'),
2: ba.getsound('announceTwo'),
1: ba.getsound('announceOne')
self._swipsound = bs.getsound('swip')
self._countdownsounds: Dict[int, babase.Sound] = {
10: bs.getsound('announceTen'),
9: bs.getsound('announceNine'),
8: bs.getsound('announceEight'),
7: bs.getsound('announceSeven'),
6: bs.getsound('announceSix'),
5: bs.getsound('announceFive'),
4: bs.getsound('announceFour'),
3: bs.getsound('announceThree'),
2: bs.getsound('announceTwo'),
1: bs.getsound('announceOne')
}
self._flag_spawn_pos: Optional[Sequence[float]] = None
self._reset_region_material: Optional[ba.Material] = None
self._reset_region_material: Optional[bs.Material] = None
self._flag: Optional[Flag] = None
self._reset_region: Optional[ba.Node] = None
self._reset_region: Optional[bs.Node] = None
self._epic_mode = bool(settings['Epic Mode'])
self._invicible_one_time = int(settings['Invicible One Time'])
self._time_limit = float(settings['Time Limit'])
@ -117,13 +120,13 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
# Base class overrides
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC
if self._epic_mode else ba.MusicType.CHOSEN_ONE)
self.default_music = (bs.MusicType.EPIC
if self._epic_mode else bs.MusicType.CHOSEN_ONE)
def get_instance_description(self) -> Union[str, Sequence]:
return 'Show your invisibility powers.'
def create_team(self, sessionteam: ba.SessionTeam) -> Team:
def create_team(self, sessionteam: bs.SessionTeam) -> Team:
return Team(time_remaining=self._invicible_one_time)
def on_team_join(self, team: Team) -> None:
@ -143,13 +146,13 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
Flag.project_stand(self._flag_spawn_pos)
self._set_invicible_one_player(None)
if self._night_mode:
gnode = ba.getactivity().globalsnode
gnode = bs.getactivity().globalsnode
gnode.tint = (0.4, 0.4, 0.4)
pos = self._flag_spawn_pos
ba.timer(1.0, call=self._tick, repeat=True)
bs.timer(1.0, call=self._tick, repeat=True)
mat = self._reset_region_material = ba.Material()
mat = self._reset_region_material = bs.Material()
mat.add_actions(
conditions=(
'they_have_material',
@ -159,11 +162,11 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', False),
('call', 'at_connect',
ba.WeakCall(self._handle_reset_collide)),
bs.WeakCall(self._handle_reset_collide)),
),
)
self._reset_region = ba.newnode('region',
self._reset_region = bs.newnode('region',
attrs={
'position': (pos[0], pos[1] + 0.75,
pos[2]),
@ -185,24 +188,24 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
# Attempt to get a Player controlling a Spaz that we hit.
try:
player = ba.getcollision().opposingnode.getdelegate(
player = bs.getcollision().opposingnode.getdelegate(
PlayerSpaz, True).getplayer(Player, True)
except ba.NotFoundError:
except bs.NotFoundError:
return
if player.is_alive():
self._set_invicible_one_player(player)
def _flash_flag_spawn(self) -> None:
light = ba.newnode('light',
light = bs.newnode('light',
attrs={
'position': self._flag_spawn_pos,
'color': (1, 1, 1),
'radius': 0.3,
'height_attenuated': False
})
ba.animate(light, 'intensity', {0: 0, 0.25: 0.5, 0.5: 0}, loop=True)
ba.timer(1.0, light.delete)
bs.animate(light, 'intensity', {0: 0, 0.25: 0.5, 0.5: 0}, loop=True)
bs.timer(1.0, light.delete)
def _tick(self) -> None:
@ -212,7 +215,7 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
# This shouldn't happen, but just in case.
if not player.is_alive():
ba.print_error('got dead player as chosen one in _tick')
babase.print_error('got dead player as chosen one in _tick')
self._set_invicible_one_player(None)
else:
scoring_team = player.team
@ -229,9 +232,7 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
# announce numbers we have sounds for
if scoring_team.time_remaining in self._countdownsounds:
ba.playsound(
self._countdownsounds[scoring_team.time_remaining])
self._countdownsounds[scoring_team.time_remaining].play()
# Winner!
if scoring_team.time_remaining <= 0:
self.end_game()
@ -242,11 +243,11 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
# (Chosen-one player ceasing to exist should
# trigger on_player_leave which resets chosen-one)
if self._invicible_one_player is not None:
ba.print_error('got nonexistent player as chosen one in _tick')
babase.print_error('got nonexistent player as chosen one in _tick')
self._set_invicible_one_player(None)
def end_game(self) -> None:
results = ba.GameResults()
results = bs.GameResults()
for team in self.teams:
results.set_team_score(team,
self._invicible_one_time - team.time_remaining)
@ -256,7 +257,7 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
existing = self._get_invicible_one_player()
if existing:
existing.chosen_light = None
ba.playsound(self._swipsound)
self._swipsound.play()
if not player:
assert self._flag_spawn_pos is not None
self._flag = Flag(color=(1, 0.9, 0.2),
@ -266,7 +267,7 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
# Create a light to highlight the flag;
# this will go away when the flag dies.
ba.newnode('light',
bs.newnode('light',
owner=self._flag.node,
attrs={
'position': self._flag_spawn_pos,
@ -287,18 +288,18 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
if self._invicible_one_is_lazy:
player.actor.connect_controls_to_player(
enable_punch=False, enable_pickup=False, enable_bomb=False)
if player.actor.node.torso_model != None:
if player.actor.node.torso_mesh != None:
player.actor.node.color_mask_texture = None
player.actor.node.color_texture = None
player.actor.node.head_model = None
player.actor.node.torso_model = None
player.actor.node.upper_arm_model = None
player.actor.node.forearm_model = None
player.actor.node.pelvis_model = None
player.actor.node.toes_model = None
player.actor.node.upper_leg_model = None
player.actor.node.lower_leg_model = None
player.actor.node.hand_model = None
player.actor.node.head_mesh = None
player.actor.node.torso_mesh = None
player.actor.node.upper_arm_mesh = None
player.actor.node.forearm_mesh = None
player.actor.node.pelvis_mesh = None
player.actor.node.toes_mesh = None
player.actor.node.upper_leg_mesh = None
player.actor.node.lower_leg_mesh = None
player.actor.node.hand_mesh = None
player.actor.node.style = 'cyborg'
invi_sound = []
player.actor.node.jump_sounds = invi_sound
@ -311,7 +312,7 @@ class InvicibleOneGame(ba.TeamGameActivity[Player, Team]):
player.actor.node.name = ''
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.PlayerDiedMessage):
# Augment standard behavior.
super().handlemessage(msg)
player = msg.getplayer(Player)

View file

@ -1,17 +1,20 @@
# ba_meta require api 7
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# ba_meta require api 8
from typing import Sequence
import ba
import _ba
import babase
import bauiv1 as bui
import bascenev1 as bs
import _babase
import random
from bastd.actor.spaz import Spaz
from bastd.actor.scoreboard import Scoreboard
from bascenev1lib.actor.spaz import Spaz
from bascenev1lib.actor.scoreboard import Scoreboard
class Player(ba.Player['Team']):
class Player(bs.Player['Team']):
"""Our player type for this game."""
class Team(ba.Team[Player]):
class Team(bs.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
@ -39,7 +42,7 @@ class ChooseingSpaz(Spaz):
super().__init__(color, highlight, "Spaz", None, True, True, False, False)
self.last_player_attacked_by = None
self.stand(pos)
self.loc = ba.newnode(
self.loc = bs.newnode(
'locator',
attrs={
'shape': 'circleOutline',
@ -51,37 +54,37 @@ class ChooseingSpaz(Spaz):
},
)
self.node.connectattr("position", self.loc, "position")
ba.animate_array(self.loc, "size", 1, keys={0: [0.5,], 1: [2,], 1.5: [0.5]}, loop=True)
bs.animate_array(self.loc, "size", 1, keys={0: [0.5,], 1: [2,], 1.5: [0.5]}, loop=True)
def handlemessage(self, msg):
if isinstance(msg, ba.FreezeMessage):
if isinstance(msg, bs.FreezeMessage):
return
if isinstance(msg, ba.PowerupMessage):
if isinstance(msg, bs.PowerupMessage):
if not (msg.poweruptype == "health"):
return
super().handlemessage(msg)
if isinstance(msg, ba.HitMessage):
self.handlemessage(ba.PowerupMessage("health"))
if isinstance(msg, bs.HitMessage):
self.handlemessage(bs.PowerupMessage("health"))
player = msg.get_source_player(Player)
if self.is_alive():
self.activity.handlemessage(ChooseingSpazHitMessage(player))
self.last_player_attacked_by = player
elif isinstance(msg, ba.DieMessage):
elif isinstance(msg, bs.DieMessage):
player = self.last_player_attacked_by
if msg.how.value != ba.DeathType.GENERIC.value:
if msg.how.value != bs.DeathType.GENERIC.value:
self._dead = True
self.activity.handlemessage(ChooseingSpazDieMessage(player))
self.loc.delete()
def stand(self, pos=(0, 0, 0), angle=0):
self.handlemessage(ba.StandMessage(pos, angle))
self.handlemessage(bs.StandMessage(pos, angle))
def recolor(self, color, highlight=(1, 1, 1)):
self.node.color = color
@ -89,14 +92,14 @@ class ChooseingSpaz(Spaz):
self.loc.color = color
class ChooseBilbord(ba.Actor):
class ChooseBilbord(bs.Actor):
def __init__(self, player: Player, delay=0.1) -> None:
super().__init__()
icon = player.get_icon()
self.scale = 100
self.node = ba.newnode(
self.node = bs.newnode(
'image',
delegate=self,
attrs={
@ -111,13 +114,13 @@ class ChooseBilbord(ba.Actor):
},
)
self.name_node = ba.newnode(
self.name_node = bs.newnode(
'text',
owner=self.node,
attrs={
'position': (60, -185),
'text': ba.Lstr(value=player.getname()),
'color': ba.safecolor(player.team.color),
'text': babase.Lstr(value=player.getname()),
'color': babase.safecolor(player.team.color),
'h_align': 'center',
'v_align': 'center',
'vr_depth': 410,
@ -128,26 +131,26 @@ class ChooseBilbord(ba.Actor):
},
)
ba.animate_array(self.node, "scale", keys={
bs.animate_array(self.node, "scale", keys={
0 + delay: [0, 0], 0.05 + delay: [self.scale, self.scale]}, size=1)
ba.animate(self.name_node, "scale", {0 + delay: 0, 0.07 + delay: 1})
bs.animate(self.name_node, "scale", {0 + delay: 0, 0.07 + delay: 1})
def handlemessage(self, msg):
super().handlemessage(msg)
if isinstance(msg, ba.DieMessage):
ba.animate_array(self.node, "scale", keys={0: self.node.scale, 0.05: [0, 0]}, size=1)
ba.animate(self.name_node, "scale", {0: self.name_node.scale, 0.07: 0})
if isinstance(msg, bs.DieMessage):
bs.animate_array(self.node, "scale", keys={0: self.node.scale, 0.05: [0, 0]}, size=1)
bs.animate(self.name_node, "scale", {0: self.name_node.scale, 0.07: 0})
def __delete():
self.node.delete()
self.name_node.delete()
ba.timer(0.2, __delete)
bs.timer(0.2, __delete)
# ba_meta export game
# ba_meta export bascenev1.GameActivity
class LastPunchStand(ba.TeamGameActivity[Player, Team]):
class LastPunchStand(bs.TeamGameActivity[Player, Team]):
name = "Last Punch Stand"
description = "Last one punchs the choosing spaz wins"
tips = [
@ -156,11 +159,11 @@ class LastPunchStand(ba.TeamGameActivity[Player, Team]):
"evry time you punch the choosing spaz, you will get one point",
]
default_music = ba.MusicType.TO_THE_DEATH
default_music = bs.MusicType.TO_THE_DEATH
available_settings = [
ba.FloatSetting("min time limit (in seconds)", 50.0, min_value=30.0),
ba.FloatSetting("max time limit (in seconds)", 160.0, 60),
bs.FloatSetting("min time limit (in seconds)", 50.0, min_value=30.0),
bs.FloatSetting("max time limit (in seconds)", 160.0, 60),
]
@ -203,12 +206,12 @@ class LastPunchStand(ba.TeamGameActivity[Player, Team]):
super().on_begin()
time_limit = random.randint(self._min_timelimit, self._max_timelimit)
self.spaw_bot()
ba.timer(time_limit, self.times_up)
bs.timer(time_limit, self.times_up)
self.setup_standard_powerup_drops(False)
def end_game(self) -> None:
results = ba.GameResults()
results = bs.GameResults()
for team in self.teams:
if self.choosed_player and (team.id == self.choosed_player.team.id):
team.score += 100
@ -261,7 +264,7 @@ class LastPunchStand(ba.TeamGameActivity[Player, Team]):
self.spaw_bot()
self.change_choosed_player(None)
elif isinstance(msg, ba.PlayerDiedMessage):
elif isinstance(msg, bs.PlayerDiedMessage):
player = msg.getplayer(Player)
if not (self.has_ended() or self.times_uped):
self.respawn_player(player, 0)

View file

@ -1,4 +1,5 @@
# ba_meta require api 7
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# ba_meta require api 8
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
@ -6,15 +7,17 @@ from __future__ import annotations
import random
from typing import TYPE_CHECKING
import ba
from bastd.actor.bomb import Bomb
from bastd.actor.onscreentimer import OnScreenTimer
import babase
import bauiv1 as bui
import bascenev1 as bs
from bascenev1lib.actor.bomb import Bomb
from bascenev1lib.actor.onscreentimer import OnScreenTimer
if TYPE_CHECKING:
from typing import Any, Sequence
lang = ba.app.lang.language
lang = bs.app.lang.language
if lang == 'Spanish':
name = 'Lluvia de Meteoritos v2'
@ -48,7 +51,7 @@ else:
random_rain = 'Random Rain'
class Player(ba.Player['Team']):
class Player(bs.Player['Team']):
"""Our player type for this game."""
def __init__(self) -> None:
@ -56,18 +59,18 @@ class Player(ba.Player['Team']):
self.death_time: float | None = None
class Team(ba.Team[Player]):
class Team(bs.Team[Player]):
"""Our team type for this game."""
# ba_meta export game
class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
# ba_meta export bascenev1.GameActivity
class MeteorShowerv2Game(bs.TeamGameActivity[Player, Team]):
"""Minigame involving dodging falling bombs."""
name = name
description = 'Dodge the falling bombs.'
scoreconfig = ba.ScoreConfig(
label='Survived', scoretype=ba.ScoreType.MILLISECONDS, version='B'
scoreconfig = bs.ScoreConfig(
label='Survived', scoretype=bs.ScoreType.MILLISECONDS, version='B'
)
# Print messages when players die (since its meaningful in this game).
@ -79,10 +82,10 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
@classmethod
def get_available_settings(
cls, sessiontype: type[ba.Session]
) -> list[ba.Setting]:
cls, sessiontype: type[bs.Session]
) -> list[babase.Setting]:
settings = [
ba.IntChoiceSetting(
bs.IntChoiceSetting(
bomb_type,
choices=[
('normal', 0),
@ -95,22 +98,22 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
],
default=0,
),
ba.BoolSetting('Epic Mode', default=False),
bs.BoolSetting('Epic Mode', default=False),
]
return settings
# We're currently hard-coded for one map.
@classmethod
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
return ['Rampage']
# We support teams, free-for-all, and co-op sessions.
@classmethod
def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool:
def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
return (
issubclass(sessiontype, ba.DualTeamSession)
or issubclass(sessiontype, ba.FreeForAllSession)
or issubclass(sessiontype, ba.CoopSession)
issubclass(sessiontype, bs.DualTeamSession)
or issubclass(sessiontype, bs.FreeForAllSession)
or issubclass(sessiontype, bs.CoopSession)
)
def __init__(self, settings: dict):
@ -138,7 +141,7 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
# Some base class overrides:
self.default_music = (
ba.MusicType.EPIC if self._epic_mode else ba.MusicType.SURVIVAL
bs.MusicType.EPIC if self._epic_mode else bs.MusicType.SURVIVAL
)
if self._epic_mode:
self.slow_motion = True
@ -152,19 +155,19 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
delay = 5.0 if len(self.players) > 2 else 2.5
if self._epic_mode:
delay *= 0.25
ba.timer(delay, self._decrement_meteor_time, repeat=True)
bs.timer(delay, self._decrement_meteor_time, repeat=True)
# Kick off the first wave in a few seconds.
delay = 3.0
if self._epic_mode:
delay *= 0.25
ba.timer(delay, self._set_meteor_timer)
bs.timer(delay, self._set_meteor_timer)
self._timer = OnScreenTimer()
self._timer.start()
# Check for immediate end (if we've only got 1 player, etc).
ba.timer(5.0, self._check_end_game)
bs.timer(5.0, self._check_end_game)
def on_player_leave(self, player: Player) -> None:
# Augment default behavior.
@ -174,7 +177,7 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
self._check_end_game()
# overriding the default character spawning..
def spawn_player(self, player: Player) -> ba.Actor:
def spawn_player(self, player: Player) -> bs.Actor:
spaz = self.spawn_player_spaz(player)
# Let's reconnect this player's controls to this
@ -189,12 +192,12 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
# Various high-level game events come through this method.
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.PlayerDiedMessage):
# Augment standard behavior.
super().handlemessage(msg)
curtime = ba.time()
curtime = bs.time()
# Record the player's moment of death.
# assert isinstance(msg.spaz.player
@ -204,15 +207,15 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
# (more accurate looking).
# In teams/ffa, allow a one-second fudge-factor so we can
# get more draws if players die basically at the same time.
if isinstance(self.session, ba.CoopSession):
if isinstance(self.session, bs.CoopSession):
# Teams will still show up if we check now.. check in
# the next cycle.
ba.pushcall(self._check_end_game)
babase.pushcall(self._check_end_game)
# Also record this for a final setting of the clock.
self._last_player_death_time = curtime
else:
ba.timer(1.0, self._check_end_game)
bs.timer(1.0, self._check_end_game)
else:
# Default handler:
@ -229,7 +232,7 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
# In co-op, we go till everyone is dead.. otherwise we go
# until one team remains.
if isinstance(self.session, ba.CoopSession):
if isinstance(self.session, bs.CoopSession):
if living_team_count <= 0:
self.end_game()
else:
@ -237,7 +240,7 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
self.end_game()
def _set_meteor_timer(self) -> None:
ba.timer(
bs.timer(
(1.0 + 0.2 * random.random()) * self._meteor_time,
self._drop_bomb_cluster,
)
@ -248,10 +251,10 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
# and debug things.
loc_test = False
if loc_test:
ba.newnode('locator', attrs={'position': (8, 6, -5.5)})
ba.newnode('locator', attrs={'position': (8, 6, -2.3)})
ba.newnode('locator', attrs={'position': (-7.3, 6, -5.5)})
ba.newnode('locator', attrs={'position': (-7.3, 6, -2.3)})
bs.newnode('locator', attrs={'position': (8, 6, -5.5)})
bs.newnode('locator', attrs={'position': (8, 6, -2.3)})
bs.newnode('locator', attrs={'position': (-7.3, 6, -5.5)})
bs.newnode('locator', attrs={'position': (-7.3, 6, -2.3)})
# Drop several bombs in series.
delay = 0.0
@ -269,7 +272,7 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
random.uniform(-3.066, -4.12),
0,
)
ba.timer(delay, ba.Call(self._drop_bomb, pos, vel))
bs.timer(delay, babase.Call(self._drop_bomb, pos, vel))
delay += 0.1
self._set_meteor_timer()
@ -294,7 +297,7 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
self._meteor_time = max(0.01, self._meteor_time * 0.9)
def end_game(self) -> None:
cur_time = ba.time()
cur_time = bs.time()
assert self._timer is not None
start_time = self._timer.getstarttime()
@ -325,7 +328,7 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
# Ok now calc game results: set a score for each team and then tell
# the game to end.
results = ba.GameResults()
results = bs.GameResults()
# Remember that 'free-for-all' mode is simply a special form
# of 'teams' mode where each player gets their own team, so we can
@ -346,58 +349,58 @@ class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]):
# ba_meta export plugin
class MeteorShowerv2Coop(ba.Plugin):
class MeteorShowerv2Coop(babase.Plugin):
def on_app_running(self) -> None:
ba.app.add_coop_practice_level(
ba.Level(
babase.app.classic.add_coop_practice_level(
bs._level.Level(
normal_rain,
gametype=MeteorShowerv2Game,
settings={bomb_type: 0},
preview_texture_name='rampagePreview',
)
)
ba.app.add_coop_practice_level(
ba.Level(
babase.app.classic.add_coop_practice_level(
bs._level.Level(
frozen_rain,
gametype=MeteorShowerv2Game,
settings={bomb_type: 1},
preview_texture_name='rampagePreview',
)
)
ba.app.add_coop_practice_level(
ba.Level(
babase.app.classic.add_coop_practice_level(
bs._level.Level(
sticky_rain,
gametype=MeteorShowerv2Game,
settings={bomb_type: 2},
preview_texture_name='rampagePreview',
)
)
ba.app.add_coop_practice_level(
ba.Level(
babase.app.classic.add_coop_practice_level(
bs._level.Level(
impact_rain,
gametype=MeteorShowerv2Game,
settings={bomb_type: 3},
preview_texture_name='rampagePreview',
)
)
ba.app.add_coop_practice_level(
ba.Level(
babase.app.classic.add_coop_practice_level(
bs._level.Level(
mine_rain,
gametype=MeteorShowerv2Game,
settings={bomb_type: 4},
preview_texture_name='rampagePreview',
)
)
ba.app.add_coop_practice_level(
ba.Level(
babase.app.classic.add_coop_practice_level(
bs._level.Level(
tnt_rain,
gametype=MeteorShowerv2Game,
settings={bomb_type: 5},
preview_texture_name='rampagePreview',
)
)
ba.app.add_coop_practice_level(
ba.Level(
babase.app.classic.add_coop_practice_level(
bs._level.Level(
random_rain,
gametype=MeteorShowerv2Game,
settings={bomb_type: 6},

View file

@ -0,0 +1,441 @@
# Usage: port_7_to_8.py <client/server type of mod> <plugin-name>
# You'll have to manually update the following:
# with ba.Context(_ba.foreground_host_activity()):
# To:
# with _ba.foreground_host_activity().context:
#
# ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
# To:
# ba.time() * 1000
#
# ba.Timer((POWERUP_WEAR_OFF_TIME - 2000),ba.WeakCall(self._multi_bomb_wear_off_flash),timeformat=ba.TimeFormat.MILLISECONDS)
# To:
# ba.Timer((POWERUP_WEAR_OFF_TIME - 2000 / 1000),ba.WeakCall(self._multi_bomb_wear_off_flash))
import re
import sys
import codecs
def detect_encoding(filename):
encodings = ['utf-8', 'latin-1', 'ascii', 'cp1252']
for encoding in encodings:
try:
with open(filename, 'rb') as f:
f.read().decode(encoding)
return encoding
except UnicodeDecodeError:
pass
return None
filename = sys.argv[2]
encoding = detect_encoding(filename)
if encoding:
with open(filename, 'r', encoding=encoding) as f:
print("Porting "+ sys.argv[2])
content = f.read()
else:
print('Could not detect encoding')
content = content.replace("# ba_meta require api 7", "# ba_meta require api 8")
content = content.replace("# ba_meta export game", "# ba_meta export bascenev1.GameActivity")
content = content.replace("user_agent_string", "legacy_user_agent_string")
content = re.sub(r'^(import\s+[\w]+(\s*,\s*[\w]+)+)', lambda match: re.sub(r'\s*,\s*', '\nimport ', match.group()), content, flags=re.MULTILINE)
content = content.replace("_ba.", "_babase.")
content = content.replace("_ba.", "_babase.")
content = content.replace("ba.", "babase.")
content = content.replace("import _ba", "import _babase")
content = content.replace("from ba import", "from babase import")
content = content.replace("from _ba import", "from _babase import")
content = re.sub(r'\bimport _ba\b', "import _babase", content)
content = re.sub(r'\bimport ba(\b|\.(\w+))', "import babase\nimport bauiv1\nimport bascenev1", content)
match = re.search(r'^(import\s+[\w]+(\s*,\s*[\w]+)*)', content, flags=re.MULTILINE)
affected_methods = ["build_number", "device_name", "config_file_path", "version", "debug_build", "test_build", "data_directory", "python_directory_user", "python_directory_app", "python_directory_app_site", "api_version", "on_tv", "vr_mode","toolbar_test", "arcade_test", "headless_mode", "demo_mode", "protocol_version", "get_connection_to_host_info"]
for word in affected_methods:
if f".{word}" in content:
first_import_index = match.start()
content = content[:first_import_index] + 'from baenv import TARGET_BALLISTICA_BUILD as build_number\n' + content[first_import_index:]
content = content.replace("babase.app.ui", "bauiv1.app.ui_v1")
content = content.replace("babase.app.accounts_v1", "bauiv1.app.classic.accounts")
###################################################################################
# Comment out one of these as per your requirements, depending whether to
# stay local or if it'll also be needed to transmitted to the clients.
## For local:
if sys.argv[1] == "client":
content = content.replace("_babase.screenmessage", "bauiv1.screenmessage")
content = content.replace("babase.screenmessage", "bauiv1.screenmessage")
content = content.replace("babase.getsound", "bauiv1.getsound")
content = content.replace("_babase.gettexture", "bauiv1.gettexture")
content = content.replace("babase.gettexture", "bauiv1.gettexture")
content = content.replace("babase.getmesh", "bauiv1.getmesh")
content = content.replace("babase.getcollisionmesh", "bauiv1.getcollisionmesh")
else:
## For transmission:
content = content.replace("_babase.screenmessage", "bascenev1.broadcastmessage")
content = content.replace("babase.screenmessage", "bascenev1.broadcastmessage")
content = content.replace("babase.getsound", "bascenev1.getsound")
content = content.replace("_babase.gettexture", "bascenev1.gettexture")
content = content.replace("babase.gettexture", "bascenev1.gettexture")
content = content.replace("babase.getmesh", "bascenev1.getmesh")
content = content.replace("babase.getcollisionmesh", "bascenev1.getcollisionmesh")
###################################################################################
content = content.replace("babase.getcollidemesh", "bascenev1.getcollisionmesh")
content = content.replace("collide_mesh", "collision_mesh")
content = content.replace("babase.open_url", "bauiv1.open_url")
content = content.replace("babase.IntSetting", "bascenev1.IntSetting")
content = content.replace("babase.IntChoiceSetting", "bascenev1.IntChoiceSetting")
content = content.replace("babase.FloatChoiceSetting", "bascenev1.FloatChoiceSetting")
content = content.replace("babase.BoolSetting", "bascenev1.BoolSetting")
content = content.replace("babase.Actor", "bascenev1.Actor")
content = content.replace("babase.Player", "bascenev1.Player")
content = content.replace("babase.PlayerDiedMessage", "bascenev1.PlayerDiedMessage")
content = content.replace("babase.time", "bascenev1.time")
content = content.replace("babase.Timer", "bascenev1.Timer")
content = content.replace("babase.newnode", "bascenev1.newnode")
content = content.replace("babase.Node", "bascenev1.Node")
content = content.replace("babase.emitfx", "bascenev1.emitfx")
content = content.replace("babase.animate", "bascenev1.animate")
content = content.replace("babase.FreeForAllSession", "bascenev1.FreeForAllSession")
content = content.replace("babase.DualTeamSession", "bascenev1.DualTeamSession")
content = content.replace("babase.MultiTeamSession", "bascenev1.MultiTeamSession")
content = content.replace("babase.EndSession", "bascenev1.EndSession")
content = content.replace("babase.CoopSession", "bascenev1.CoopSession")
content = content.replace("babase.TeamGameActivity", "bascenev1.TeamGameActivity")
content = content.replace("babase.Team", "bascenev1.Team")
content = content.replace("babase.Session", "bascenev1.Session")
content = content.replace("babase.getsession", "bascenev1.getsession")
content = content.replace("babase.Material", "bascenev1.Material")
content = content.replace("babase.WeakCall", "bascenev1.WeakCall")
content = content.replace("babase.DieMessage", "bascenev1.DieMessage")
content = content.replace("babase.OutOfBoundsMessage", "bascenev1.OutOfBoundsMessage")
content = content.replace("babase.DroppedMessage", "bascenev1.DroppedMessage")
content = content.replace("babase.HitMessage", "bascenev1.HitMessage")
content = content.replace("babase.ThawMessage", "bascenev1.ThawMessage")
content = content.replace("babase.NotFoundError", "bascenev1.NotFoundError")
content = content.replace("babase.getcollision", "bascenev1.getcollision")
content = content.replace("babase.app.lang", "bascenev1.app.lang")
content = content.replace("babase.MusicType", "bascenev1.MusicType")
content = content.replace("babase.getactivity", "bascenev1.getactivity")
content = content.replace("babase.getactivity", "bascenev1.getactivity")
content = content.replace("babase.CelebrateMessage", "bascenev1.CelebrateMessage")
content = content.replace("babase.ScoreConfig", "bascenev1.ScoreConfig")
content = content.replace("babase.ScoreType", "bascenev1.ScoreType")
content = content.replace("babase.GameResults", "bascenev1.GameResults")
content = content.replace("babase.getmaps", "bascenev1.app.classic.getmaps")
content = content.replace("babase.cameraflash", "bascenev1.cameraflash")
content = content.replace("babase.getmodel", "bascenev1.getmesh")
content = content.replace("babase.Map", "bascenev1.Map")
content = content.replace("babase.DeathType", "bascenev1.DeathType")
content = content.replace("babase.GameActivity", "bascenev1.GameActivity")
content = content.replace("_babase.app.stress_test_reset_timer", "_babase.app.classic.stress_test_reset_timer")
content = content.replace("babase.app.stress_test_reset_timer", "_babase.app.classic.stress_test_reset_timer")
content = content.replace("babase._map", "bascenev1._map")
content = content.replace("babase._session.", "bascenev1._session.")
content = content.replace("babase._activity", "bascenev1._activity")
content = content.replace("_babase.get_client_public_device_uuid", "_bascenev1.get_client_public_device_uuid")
content = content.replace("babase.PickedUpMessage", "bascenev1.PickedUpMessage")
content = content.replace("babase.PowerupMessage", "bascenev1.PowerupMessage")
content = content.replace("babase.FreezeMessage", "bascenev1.FreezeMessage")
content = content.replace("with babase.ContextRef(activity):", "with activity.context:")
content = content.replace("babase.Context", "babase.ContextRef")
content = content.replace("babase._dualteamsession", "bascenev1._dualteamsession")
content = content.replace("babase._freeforallsession", "bascenev1._freeforallsession")
content = content.replace("babase._multiteamsession", "bascenev1._multiteamsession")
content = content.replace("babase._gameactivity", "bascenev1._gameactivity")
content = content.replace("babase._powerup", "bascenev1._powerup")
content = content.replace("babase.Chooser", "bascenev1.Chooser")
content = content.replace("babase._lobby", "bascenev1._lobby")
content = content.replace("babase._stats", "bascenev1._stats")
content = content.replace("babase._team", "bascenev1._team")
content = content.replace("PlayerType", "PlayerT")
content = content.replace("babase.app.spaz_appearances", "babase.app.classic.spaz_appearances")
content = content.replace("babase._coopsession", "bascenev1._coopsession")
content = content.replace("babase._servermode", "baclassic._servermode")
content = content.replace("_babase.app.server", "babase.app.classic.server")
content = content.replace("_babase.chatmessage", "bascenev1.chatmessage")
content = content.replace("_babase.disconnect_client", "_bascenev1.disconnect_client")
content = content.replace("_babase.get_game_roster", "bascenev1.get_game_roster")
content = content.replace("_babase.get_public_party_max_size", "bascenev1.get_public_party_max_size")
content = content.replace("_babase.new_host_session", "bascenev1.new_host_session")
content = content.replace("babase._playlist", "bascenev1._playlist")
content = content.replace("model", "mesh")
content = content.replace("TimeType.REAL", "use `bascenev1.apptimer` in `activity.context` instead")
content = content.replace("_babase.app.coop_session_args", "babase.app.classic.coop_session_args")
content = content.replace("_babase.app.campaigns", "babase.app.classic.campaigns")
content = content.replace("_babase.newactivity", "bascenev1.newactivity")
content = content.replace("babase.Window", "bauiv1.Window")
content = content.replace("babase.Widget", "bauiv1.Widget")
content = content.replace("babase.widget", "bauiv1.widget")
content = content.replace("babase.containerwidget", "bauiv1.containerwidget")
content = content.replace("babase.scrollwidget", "bauiv1.scrollwidget")
content = content.replace("babase.buttonwidget", "bauiv1.buttonwidget")
content = content.replace("babase.textwidget", "bauiv1.textwidget")
content = content.replace("babase.checkboxwidget", "bauiv1.checkboxwidget")
content = content.replace("babase.imagewidget", "bauiv1.imagewidget")
content = content.replace("babase.uicleanupcheck", "bauiv1.uicleanupcheck")
content = content.replace("_babase.set_public_party_max_size", "bascenev1.set_public_party_max_size")
content = content.replace("_bauiv1", "bauiv1")
content = content.replace("babase.show_damage_count", "bascenev1.show_damage_count")
content = content.replace("babase._gameutils", "bascenev1._gameutils")
content = content.replace("babase.StandMessage", "bascenev1.StandMessage")
content = content.replace("babase.PowerupAcceptMessage", "bascenev1.PowerupAcceptMessage")
content = content.replace("babase._gameutils", "bascenev1._gameutils")
content = content.replace("babase.camerashake", "bascenev1.camerashake")
content = content.replace("babase.app.add_coop_practice_level", "babase.app.classic.add_coop_practice_level")
content = content.replace("babase._campaign", "bascenev1._campaign")
content = content.replace("babase.Level", "bascenev1._level.Level")
content = content.replace("babase.app.cloud.send_message_cb", "bauiv1.app.plus.cloud.send_message_cb")
content = content.replace("_babase.get_special_widget", "bauiv1.get_special_widget")
content = content.replace(".app.platform", ".app.classic.platform")
content = content.replace(".app.subplatform", ".app.classic.subplatform")
content = content.replace(".getlog", ".get_v1_cloud_log")
# Converting `ba.playsound(abc)` to `abc.play()` is tricky.
# Do it manually in case regex substitution fails.# Do it manually in case regex substitution fails. Are you sure!!
#! FIXME May cause syntax warning on 3.12
content = re.sub(
r'babase\.playsound\(\s*([^,\n]+),\s*([^,\n]+)\)',
r'\1.play(\2)',
content,
flags=re.MULTILINE
)
content = re.sub(
r'babase\.playsound\(\s*([^,\n]+),\s*([^,\n]+),\s*position=([^,\n]+)\)',
r'\1.play(\2, position=\3)',
content,
flags=re.MULTILINE
)
content = re.sub("babase\.playsound\((.+?), (.+?), (.+?)\)", "\\1.play(\\2, \\3)", content)
content = re.sub(
r'babase\.playsound\(([^,\n]+),\s*position=([^,\n]+)\)',
r'\1.play(position=\2)',
content
)
content = re.sub("babase\.playsound\((.*)\)", "\\1.play()", content)
content = content.replace("babase.internal.add_transaction", "bauiv1.app.plus.add_v1_account_transaction")
content = content.replace("babase.internal.run_transaction", "bauiv1.app.plus.run_v1_account_transaction")
content = content.replace("_babase.add_transaction", "bauiv1.app.plus.add_v1_account_transaction")
content = content.replace("_babase.run_transactions", "bauiv1.app.plus.run_v1_account_transactions")
content = content.replace("babase._store.get_store_layout", "bauiv1.app.classic.store.get_store_layout")
content = content.replace("babase.internal.get_store_layout", "bauiv1.app.classic.store.get_store_layout")
content = content.replace("babase.internal.connect_to_party", "bascenev1.connect_to_party")
content = content.replace("babase.internal.get_default_powerup_distribution", "bascenev1._powerup.get_default_powerup_distribution")
content = content.replace("babase.internal.DEFAULT_REQUEST_TIMEOUT_SECONDS", "babase.DEFAULT_REQUEST_TIMEOUT_SECONDS")
content = content.replace("babase.internal.DEFAULT_TEAM_COLORS", "bascenev1.DEFAULT_TEAM_COLORS")
content = content.replace("babase.internal.DEFAULT_TEAM_NAMES", "bascenev1.DEFAULT_TEAM_NAMES")
content = content.replace("babase.internal.JoinActivity", "bascenev1.JoinActivity")
content = content.replace("babase.internal.LoginAdapter", "babase._login.LoginAdapter")
content = content.replace("babase.internal.PlayerProfilesChangedMessage", "bascenev1._messages.PlayerProfilesChangedMessage")
content = content.replace("babase.internal.ScoreScreenActivity", "bascenev1.ScoreScreenActivity")
content = content.replace("babase.internal.add_clean_frame_callback", "babase.add_clean_frame_callback")
content = content.replace("babase.internal.android_get_external_files_dir", "babase.android_get_external_files_dir")
content = content.replace("babase.internal.appname", "babase.appname")
content = content.replace("babase.internal.appnameupper", "babase.appnameupper")
content = content.replace("babase.internal.capture_gamepad_input", "bascenev1.capture_gamepad_input")
content = content.replace("babase.internal.capture_keyboard_input", "bascenev1.capture_keyboard_input")
content = content.replace("babase.internal.charstr", "babase.charstr")
content = content.replace("babase.internal.chatmessage", "bascenev1.chatmessage")
content = content.replace("babase.internal.commit_app_config", "bauiv1.commit_app_config")
content = content.replace("babase.internal.disconnect_client", "bascenev1.disconnect_client")
content = content.replace("babase.internal.disconnect_from_host", "bascenev1.disconnect_from_host")
content = content.replace("babase.internal.do_play_music", "babase.app.classic.music.do_play_music")
content = content.replace("babase.internal.end_host_scanning", "bascenev1.end_host_scanning")
content = content.replace("babase.internal.fade_screen", "bauiv1.fade_screen")
content = content.replace("babase.internal.filter_playlist", "bascenev1.filter_playlist")
content = content.replace("babase.internal.game_service_has_leaderboard", "_baplus.game_service_has_leaderboard")
content = content.replace("babase.internal.get_available_purchase_count", "bauiv1.app.classic.store.get_available_purchase_count")
content = content.replace("babase.internal.get_available_sale_time", "bauiv1.app.classic.store.get_available_sale_time")
content = content.replace("babase.internal.get_chat_messages", "bascenev1.get_chat_messages")
content = content.replace("babase.internal.get_clean_price", "bauiv1.app.classic.store.get_clean_price")
content = content.replace("babase.internal.get_connection_to_host_info", "bascenev1.get_connection_to_host_info_2")
content = content.replace("babase.internal.get_default_free_for_all_playlist", "bascenev1._playlist.get_default_free_for_all_playlist")
content = content.replace("babase.internal.get_default_teams_playlist", "bascenev1._playlist.get_default_teams_playlist")
content = content.replace("babase.internal.get_display_resolution", "babase.get_display_resolution")
content = content.replace("babase.internal.get_filtered_map_name", "bascenev1._map.get_filtered_map_name")
content = content.replace("babase.internal.get_foreground_host_session", "bascenev1.get_foreground_host_session")
content = content.replace("babase.internal.get_game_port", "bascenev1.get_game_port")
content = content.replace("babase.internal.get_game_roster", "bascenev1.get_game_roster")
content = content.replace("babase.internal.get_input_device_config", "bauiv1.app.classic.get_input_device_config")
content = content.replace("babase.internal.get_ip_address_type", "babase.get_ip_address_type")
content = content.replace("babase.internal.get_local_active_input_devices_count", "bascenev1.get_local_active_input_devices_count")
content = content.replace("babase.internal.get_low_level_config_value", "bauiv1.get_low_level_config_value")
content = content.replace("babase.internal.get_map_class", "bascenev1.get_map_class")
content = content.replace("babase.internal.get_map_display_string", "bascenev1.get_map_display_string")
content = content.replace("babase.internal.get_master_server_address", "bauiv1.app.plus.get_master_server_address")
content = content.replace("babase.internal.get_max_graphics_quality", "babase.get_max_graphics_quality")
content = content.replace("babase.internal.get_news_show", "_babase.app.plus.get_news_show")
content = content.replace("babase.internal.get_next_tip", "bascenev1.app.classic.get_next_tip")
content = content.replace("babase.internal.get_player_colors", "bascenev1.get_player_colors")
content = content.replace("babase.internal.get_player_profile_colors", "bascenev1.get_player_profile_colors")
content = content.replace("babase.internal.get_player_profile_icon", "bascenev1.get_player_profile_icon")
content = content.replace("babase.internal.get_price", "bauiv1.app.plus.get_price")
content = content.replace("babase.internal.get_public_party_enabled", "bascenev1.get_public_party_enabled")
content = content.replace("babase.internal.get_public_party_max_size", "bascenev1.get_public_party_max_size")
content = content.replace("babase.internal.get_purchased", "bauiv1.app.plus.get_purchased")
content = content.replace("babase.internal.get_purchases_state", "_baplus.get_purchases_state")
content = content.replace("babase.internal.get_qrcode_texture", "bauiv1.get_qrcode_texture")
content = content.replace("babase.internal.get_random_names", "bascenev1.get_random_names")
content = content.replace("babase.internal.get_remote_app_name", "bascenev1.get_remote_app_name")
content = content.replace("babase.internal.get_replay_speed_exponent", "bascenev1.get_replay_speed_exponent")
content = content.replace("babase.internal.get_replays_dir", "babase.get_replays_dir")
content = content.replace("babase.internal.get_special_widget", "bauiv1.get_special_widget")
content = content.replace("babase.internal.get_store_item", "babase.app.classic.store.get_store_item")
content = content.replace("babase.internal.get_store_item_display_size", "babase.app.classic.store.get_store_item_display_size")
content = content.replace("babase.internal.get_store_item_name_translated", "babase.app.classic.store.get_store_item_name_translated")
content = content.replace("babase.internal.get_string_height", "babase.get_string_height")
content = content.replace("babase.internal.get_string_width", "babase.get_string_width")
content = content.replace("babase.internal.get_tournament_prize_strings", "bascenev1.app.classic.get_tournament_prize_strings")
content = content.replace("babase.internal.get_trophy_string", "bascenev1.get_trophy_string")
content = content.replace("babase.internal.get_type_name", "babase.get_type_name")
content = content.replace("babase.internal.get_ui_input_device", "bascenev1.get_ui_input_device")
content = content.replace("babase.internal.get_unowned_game_types", "babase.app.classic.store.get_unowned_game_types")
content = content.replace("babase.internal.get_unowned_maps", "babase.app.classic.store.get_unowned_maps")
content = content.replace("babase.internal.get_v1_account_display_string", "bauiv1.app.plus.get_v1_account_display_string")
content = content.replace("babase.internal.get_v1_account_misc_read_val", "bauiv1.app.plus.get_v1_account_misc_read_val")
content = content.replace("babase.internal.get_v1_account_misc_read_val_2", "bauiv1.app.plus.get_v1_account_misc_read_val_2")
content = content.replace("babase.internal.get_v1_account_misc_val", "bauiv1.app.plus.get_v1_account_misc_val")
content = content.replace("babase.internal.get_v1_account_name", "bauiv1.app.plus.get_v1_account_name")
content = content.replace("babase.internal.get_v1_account_state", "bauiv1.app.plus.get_v1_account_state")
content = content.replace("babase.internal.get_v1_account_state_num", "bauiv1.app.plus.get_v1_account_state_num")
content = content.replace("babase.internal.get_v1_account_ticket_count", "bauiv1.app.plus.get_v1_account_ticket_count")
content = content.replace("babase.internal.get_v1_account_type", "bauiv1.app.plus.get_v1_account_type")
content = content.replace("babase.internal.get_v2_fleet", "_baplus.get_v2_fleet")
content = content.replace("babase.internal.getcampaign", "bauiv1.app.classic.getcampaign")
content = content.replace("babase.internal.getclass", "babase.getclass")
content = content.replace("babase.internal.getinputdevice", "bascenev1.getinputdevice")
content = content.replace("babase.internal.has_gamma_control", "babase.has_gamma_control")
content = content.replace("babase.internal.has_video_ads", "bauiv1.has_video_ads")
content = content.replace("babase.internal.have_incentivized_ad", "bauiv1.have_incentivized_ad")
content = content.replace("babase.internal.have_permission", "babase.have_permission")
content = content.replace("babase.internal.have_touchscreen_input", "bascenev1.have_touchscreen_input")
content = content.replace("babase.internal.host_scan_cycle", "bascenev1.host_scan_cycle")
content = content.replace("babase.internal.in_game_purchase", "bui.app.plus.in_game_purchase")
content = content.replace("babase.internal.increment_analytics_count", "babase.increment_analytics_count")
content = content.replace("babase.internal.is_blessed", "bui.app.plus.is_blessed")
content = content.replace("babase.internal.is_browser_likely_available", "bauiv1.is_browser_likely_available")
content = content.replace("babase.internal.is_in_replay", "bascenev1.is_in_replay")
content = content.replace("babase.internal.is_party_icon_visible", "bauiv1.is_party_icon_visible")
content = content.replace("babase.internal.is_running_on_fire_tv", "babase.is_running_on_fire_tv")
content = content.replace("babase.internal.is_xcode_build", "babase.is_xcode_build")
content = content.replace("babase.internal.json_prep", "babase.json_prep")
content = content.replace("babase.internal.lock_all_input", "babase.lock_all_input")
content = content.replace("babase.internal.mark_config_dirty", "_babase.app.plus.mark_config_dirty")
content = content.replace("babase.internal.new_host_session", "bascenev1.new_host_session")
content = content.replace("babase.internal.new_replay_session", "bascenev1.new_replay_session")
content = content.replace("babase.internal.open_file_externally", "bauiv1.open_file_externally")
content = content.replace("babase.internal.power_ranking_query", "_baplus.power_ranking_query")
content = content.replace("babase.internal.preload_map_preview_media", "bauiv1.app.classic.preload_map_preview_media")
content = content.replace("babase.internal.purchase", "_baplus.purchase")
content = content.replace("babase.internal.register_map", "bascenev1.register_map")
content = content.replace("babase.internal.release_gamepad_input", "bascenev1.release_gamepad_input")
content = content.replace("babase.internal.release_keyboard_input", "bascenev1.release_keyboard_input")
content = content.replace("babase.internal.report_achievement", "babase.app.plus.report_achievement")
content = content.replace("babase.internal.request_permission", "babase.request_permission")
content = content.replace("babase.internal.reset_achievements", "_baplus.reset_achievements")
content = content.replace("babase.internal.reset_random_player_names", "bascenev1.reset_random_player_names")
content = content.replace("babase.internal.restore_purchases", "_baplus.restore_purchases")
content = content.replace("babase.internal.run_cpu_benchmark", "baclassic._benchmark.run_cpu_benchmark")
content = content.replace("babase.internal.run_gpu_benchmark", "baclassic._benchmark.run_gpu_benchmark")
content = content.replace("babase.internal.run_media_reload_benchmark", "baclassic._benchmark.run_media_reload_benchmark")
content = content.replace("babase.internal.run_stress_test", "babase.app.classic.run_stress_test")
content = content.replace("babase.internal.set_authenticate_clients", "bascenev1.set_authenticate_clients")
content = content.replace("babase.internal.set_debug_speed_exponent", "bascenev1.set_debug_speed_exponent")
content = content.replace("babase.internal.set_low_level_config_value", "babase.set_low_level_config_value")
content = content.replace("babase.internal.set_party_icon_always_visible", "bauiv1.set_party_icon_always_visible")
content = content.replace("babase.internal.set_party_window_open", "bauiv1.set_party_window_open")
content = content.replace("babase.internal.set_public_party_enabled", "bascenev1.set_public_party_enabled")
content = content.replace("babase.internal.set_public_party_max_size", "bascenev1.set_public_party_max_size")
content = content.replace("babase.internal.set_public_party_name", "bascenev1.set_public_party_name")
content = content.replace("babase.internal.set_public_party_queue_enabled", "bascenev1.set_public_party_queue_enabled")
content = content.replace("babase.internal.set_replay_speed_exponent", "bascenev1.set_replay_speed_exponent")
content = content.replace("babase.internal.set_touchscreen_editing", "bascenev1.set_touchscreen_editing")
content = content.replace("babase.internal.set_ui_input_device", "babase.set_ui_input_device")
content = content.replace("babase.internal.should_submit_debug_info", "babase._apputils.should_submit_debug_info")
content = content.replace("babase.internal.show_online_score_ui", "bauiv1.show_online_score_ui")
content = content.replace("babase.internal.sign_in_v1", "babase.app.plus.sign_in_v1")
content = content.replace("babase.internal.sign_out_v1", "babase.app.plus.sign_out_v1")
content = content.replace("babase.internal.submit_score", "bascenev1.app.plus.submit_score")
content = content.replace("babase.internal.tournament_query", "_baplus.tournament_query")
content = content.replace("babase.internal.unlock_all_input", "babase.unlock_all_input")
content = content.replace("babase.internal.value_test", "bauiv1.app.classic.value_test")
content = content.replace("babase.internal.workspaces_in_use", "babase.workspaces_in_use")
content = content.replace("babase.internal.dump_tracebacks", "babase._apputils.dump_app_state")
content = content.replace("babase.internal.show_app_invite", "_bauiv1.show_app_invite")
content = content.replace("babase._generated", "babase._mgen")
content = content.replace("_babase.disconnect_from_host", "bascenev1.disconnect_from_host")
content = content.replace("babase.disconnect_from_host", "bascenev1.disconnect_from_host")
content = content.replace("_babase.connect_to_party", "bascenev1.connect_to_party")
content = content.replace("babase.connect_to_party", "bascenev1.connect_to_party")
content = content.replace("babase.set_party_window_open", "bauiv1.set_party_window_open")
content = content.replace("babase.set_party_window_open", "bauiv1.set_party_window_open")
content = content.replace("babase.getcollidemesh", "bascenev1.getcollisionmesh")
content = content.replace("collide_mesh", "collision_mesh")
content = content.replace("babase.FloatSetting", "bascenev1.FloatSetting")
# Removed in API 8:
# content = content.replace("babase.internal.set_telnet_access_enabled", "")
content = content.replace("babase.internal.master_server_get", "babase.app.classic.master_server_v1_get")
content = content.replace("babase.internal.master_server_post", "babase.app.classic.master_server_v1_post")
content = content.replace("babase.internal.log_dumped_tracebacks", "babase._apputils.log_dumped_app_state")
content = content.replace("babase.internal.have_outstanding_transactions", "bauiv1.app.plus.have_outstanding_v1_account_transactions")
content = content.replace("babase.internal.get_public_login_id", "bauiv1.app.plus.get_v1_account_public_login_id")
content = content.replace("babase.internal.get_input_map_hash", "bauiv1.app.classic.get_input_device_map_hash")
content = content.replace("babase.internal.get_device_value", "bauiv1.app.classic.get_input_device_mapped_value")
# Depracations
content = content.replace("babase.app.build_number", "babase.app.build_number if build_number < 21282 else babase.app.env.build_number")
content = content.replace("babase.app.device_name", "babase.app.device_name if build_number < 21282 else babase.app.env.device_name")
content = content.replace("babase.app.config_file_path", "babase.app.config_file_path if build_number < 21282 else babase.app.env.config_file_path")
content = content.replace("babase.app.version", "babase.app.version if build_number < 21282 else babase.app.env")
content = content.replace("babase.app.debug_build", "babase.app.debug_build if build_number < 21282 else babase.app.env.debug_build")
content = content.replace("babase.app.test_build", "babase.app.test_build if build_number < 21282 else babase.app.env.test_build")
content = content.replace("babase.app.data_directory", "babase.app.data_directory if build_number < 21282 else babase.app.env.data_directory")
content = content.replace("babase.app.python_directory_user", "babase.app.python_directory_user if build_number < 21282 else babase.app.env.python_directory_user")
content = content.replace("babase.app.python_directory_app", "babase.app.env")
content = content.replace("babase.app.python_directory_app_site", "babase.app.python_directory_app_site if build_number < 21282 else babase.app.env.python_directory_app_site")
content = content.replace("babase.app.api_version", "babase.app.api_version if build_number < 21282 else babase.app.env.api_version")
content = content.replace("babase.app.on_tv", "babase.app.on_tv if build_number < 21282 else babase.app.env.on_tv")
content = content.replace("babase.app.vr_mode", "babase.app.vr_mode if build_number < 21282 else babase.app.env.vr")
content = content.replace("babase.app.toolbar_test", "babase.app.toolbar_test if build_number < 21282 else babase.app.env.toolbar_test")
content = content.replace("babase.app.arcade_mode", "babase.app.arcade_mode if build_number < 21282 else babase.app.env.arcade_mode")
content = content.replace("babase.app.headless_mode", "babase.app.headless_mode if build_number < 21282 else babase.app.env.headless_mode")
content = content.replace("babase.app.demo_mode", "babase.app.demo_mode if build_number < 21282 else babase.app.env.demo_mode")
content = content.replace("babase.app.protocol_version", "babase.app.protocol_version if build_number < 21282 else babase.app.env.protocol_version")
content = content.replace("bascenev1.get_connection_to_host_info", "bascenev1.get_connection_to_host_info if build_number < 21697 else bascenev1.get_connection_to_host_info_2")
content = content.replace("babase._store", "bauiv1.app.classic.store")
# content = content.replace("babase.internal", "")
content = content.replace("bastd.ui", "bauiv1lib")
content = content.replace("bastd", "bascenev1lib")
content = content.replace("timetype=","")
content = content.replace("babase.columnwidget", "bauiv1.columnwidget")
content = content.replace("_babase.get_game_port", "bascenev1.get_game_port")
content = content.replace("_babase.get_chat_messages", "bascenev1.get_chat_messages")
content = content.replace("_babase.get_foreground_host_session", "bascenev1.get_foreground_host_session")
content = content.replace("_babase.get_foreground_host_activity", "bascenev1.get_foreground_host_activity")
content = content.replace("bascenev1.SessionPlayerNotFoundError", "babase.SessionPlayerNotFoundError")
content = content.replace("bascenev1", "bs")
content = content.replace("bauiv1", "bui")
content = content.replace("import bs", "import bascenev1 as bs")
content = content.replace("import bui", "import bauiv1 as bui")
content = content.replace("bslib", "bascenev1lib")
content = content.replace("builib", "bauiv1lib")
content = content.replace("from bs.", "from bascenev1.")
content = content.replace("from bui.", "from bauiv1.")
content = content.replace("import bascenev1 as bascenev1lib", "import bascenev1lib")
content = content.replace("import bauiv1 as bauiv1lib", "import bauiv1lib")
content = content.replace("# ba_meta export bs.GameActivity", "# ba_meta export bascenev1.GameActivity")
content = content.replace("_bs", "bs")
content = re.sub(r'bs\.Timer\(([^)]*)\bTimeType\.REAL\b([^)]*)\)', r'babase.AppTimer(\1\2)', content)
trademark = "# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)\n"
with open(sys.argv[2], "w", encoding=encoding) as f:
f.write(trademark + content)

View file

@ -1,24 +1,27 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
"""Quake Game Activity"""
# ba_meta require api 7
# ba_meta require api 8
from __future__ import annotations
from typing import TYPE_CHECKING
import random
import enum
import ba
import _ba
import babase
import bauiv1 as bui
import bascenev1 as bs
import _babase
from bastd.actor.scoreboard import Scoreboard
from bastd.actor.powerupbox import PowerupBox
from bastd.gameutils import SharedObjects
from bascenev1lib.actor.scoreboard import Scoreboard
from bascenev1lib.actor.powerupbox import PowerupBox
from bascenev1lib.gameutils import SharedObjects
# from rocket
from bastd.actor.bomb import Blast
from bascenev1lib.actor.bomb import Blast
# from railgun
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.spaz import Spaz
from bascenev1lib.actor.playerspaz import PlayerSpaz
from bascenev1lib.actor.spaz import Spaz
if TYPE_CHECKING:
@ -33,7 +36,7 @@ class RocketFactory:
"""Quake Rocket factory"""
def __init__(self) -> None:
self.ball_material = ba.Material()
self.ball_material = bs.Material()
self.ball_material.add_actions(
conditions=((('we_are_younger_than', 5), 'or',
@ -60,7 +63,7 @@ class RocketFactory:
@classmethod
def get(cls):
"""Get factory if exists else create new"""
activity = ba.getactivity()
activity = bs.getactivity()
if hasattr(activity, STORAGE_ATTR_NAME):
return getattr(activity, STORAGE_ATTR_NAME)
factory = cls()
@ -77,13 +80,13 @@ class RocketLauncher:
def give(self, spaz: Spaz) -> None:
"""Give spaz a rocket launcher"""
spaz.punch_callback = self.shot
self.last_shot = ba.time()
self.last_shot = bs.time()
# FIXME
# noinspection PyUnresolvedReferences
def shot(self, spaz: Spaz) -> None:
"""Release a rocket"""
time = ba.time()
time = bs.time()
if time - self.last_shot > 0.6:
self.last_shot = time
center = spaz.node.position_center
@ -92,12 +95,12 @@ class RocketLauncher:
center[2] - forward[2]]
direction[1] = 0.0
mag = 10.0 / ba.Vec3(*direction).length()
mag = 10.0 / babase.Vec3(*direction).length()
vel = [v * mag for v in direction]
Rocket(position=spaz.node.position,
velocity=vel,
owner=spaz.getplayer(ba.Player),
source_player=spaz.getplayer(ba.Player),
owner=spaz.getplayer(bs.Player),
source_player=spaz.getplayer(bs.Player),
color=spaz.node.color).autoretain()
@ -105,7 +108,7 @@ class ImpactMessage:
"""Rocket touched something"""
class Rocket(ba.Actor):
class Rocket(bs.Actor):
"""Epic rocket from rocket launcher"""
def __init__(self,
@ -120,16 +123,16 @@ class Rocket(ba.Actor):
self._color = color
factory = RocketFactory.get()
self.node = ba.newnode('prop',
self.node = bs.newnode('prop',
delegate=self,
attrs={
'position': position,
'velocity': velocity,
'model': ba.getmodel('impactBomb'),
'mesh': bs.getmesh('impactBomb'),
'body': 'sphere',
'color_texture': ba.gettexture(
'color_texture': bs.gettexture(
'bunnyColor'),
'model_scale': 0.2,
'mesh_scale': 0.2,
'is_area_of_interest': True,
'body_scale': 0.8,
'materials': [
@ -139,17 +142,17 @@ class Rocket(ba.Actor):
self.node.extra_acceleration = (self.node.velocity[0] * 200, 0,
self.node.velocity[2] * 200)
self._life_timer = ba.Timer(
5, ba.WeakCall(self.handlemessage, ba.DieMessage()))
self._life_timer = bs.Timer(
5, bs.WeakCall(self.handlemessage, bs.DieMessage()))
self._emit_timer = ba.Timer(0.001, ba.WeakCall(self.emit), repeat=True)
self._emit_timer = bs.Timer(0.001, bs.WeakCall(self.emit), repeat=True)
self.base_pos_y = self.node.position[1]
ba.camerashake(5.0)
bs.camerashake(5.0)
def emit(self) -> None:
"""Emit a trace after rocket"""
ba.emitfx(position=self.node.position,
bs.emitfx(position=self.node.position,
scale=0.4,
spread=0.01,
chunk_type='spark')
@ -157,7 +160,7 @@ class Rocket(ba.Actor):
return
self.node.position = (self.node.position[0], self.base_pos_y,
self.node.position[2]) # ignore y
ba.newnode('explosion',
bs.newnode('explosion',
owner=self.node,
attrs={
'position': self.node.position,
@ -169,9 +172,9 @@ class Rocket(ba.Actor):
"""Message handling for rocket"""
super().handlemessage(msg)
if isinstance(msg, ImpactMessage):
self.node.handlemessage(ba.DieMessage())
self.node.handlemessage(bs.DieMessage())
elif isinstance(msg, ba.DieMessage):
elif isinstance(msg, bs.DieMessage):
if self.node:
Blast(position=self.node.position,
blast_radius=2,
@ -180,8 +183,8 @@ class Rocket(ba.Actor):
self.node.delete()
self._emit_timer = None
elif isinstance(msg, ba.OutOfBoundsMessage):
self.handlemessage(ba.DieMessage())
elif isinstance(msg, bs.OutOfBoundsMessage):
self.handlemessage(bs.DieMessage())
# -------------------Rocket--------------------------
@ -196,13 +199,13 @@ class Railgun:
def give(self, spaz: Spaz) -> None:
"""Give spaz a railgun"""
spaz.punch_callback = self.shot
self.last_shot = ba.time()
self.last_shot = bs.time()
# FIXME
# noinspection PyUnresolvedReferences
def shot(self, spaz: Spaz) -> None:
"""Release a rocket"""
time = ba.time()
time = bs.time()
if time - self.last_shot > 0.6:
self.last_shot = time
center = spaz.node.position_center
@ -215,8 +218,8 @@ class Railgun:
RailBullet(position=spaz.node.position,
direction=direction,
owner=spaz.getplayer(ba.Player),
source_player=spaz.getplayer(ba.Player),
owner=spaz.getplayer(bs.Player),
source_player=spaz.getplayer(bs.Player),
color=spaz.node.color).autoretain()
@ -227,7 +230,7 @@ class TouchedToSpazMessage:
self.spaz = spaz
class RailBullet(ba.Actor):
class RailBullet(bs.Actor):
"""Railgun bullet"""
def __init__(self,
@ -239,23 +242,23 @@ class RailBullet(ba.Actor):
super().__init__()
self._color = color
self.node = ba.newnode('light',
self.node = bs.newnode('light',
delegate=self,
attrs={
'position': position,
'color': self._color
})
ba.animate(self.node, 'radius', {0: 0, 0.1: 0.5, 0.5: 0})
bs.animate(self.node, 'radius', {0: 0, 0.1: 0.5, 0.5: 0})
self.source_player = source_player
self.owner = owner
self._life_timer = ba.Timer(
0.5, ba.WeakCall(self.handlemessage, ba.DieMessage()))
self._life_timer = bs.Timer(
0.5, bs.WeakCall(self.handlemessage, bs.DieMessage()))
pos = position
vel = tuple(i / 5 for i in ba.Vec3(direction).normalized())
vel = tuple(i / 5 for i in babase.Vec3(direction).normalized())
for _ in range(500): # Optimization :(
ba.newnode('explosion',
bs.newnode('explosion',
owner=self.node,
attrs={
'position': pos,
@ -264,25 +267,25 @@ class RailBullet(ba.Actor):
})
pos = (pos[0] + vel[0], pos[1] + vel[1], pos[2] + vel[2])
for node in _ba.getnodes():
for node in _babase.getnodes():
if node and node.getnodetype() == 'spaz':
# pylint: disable=invalid-name
m3 = ba.Vec3(position)
a = ba.Vec3(direction[2], direction[1], direction[0])
m1 = ba.Vec3(node.position)
m3 = babase.Vec3(position)
a = babase.Vec3(direction[2], direction[1], direction[0])
m1 = babase.Vec3(node.position)
# pylint: enable=invalid-name
# distance between node and line
dist = (a * (m1 - m3)).length() / a.length()
if dist < 0.3:
if node and node != self.owner and node.getdelegate(
PlayerSpaz, True).getplayer(
ba.Player, True).team != self.owner.team:
node.handlemessage(ba.FreezeMessage())
bs.Player, True).team != self.owner.team:
node.handlemessage(bs.FreezeMessage())
pos = self.node.position
hit_dir = (0, 10, 0)
node.handlemessage(
ba.HitMessage(pos=pos,
bs.HitMessage(pos=pos,
magnitude=50,
velocity_magnitude=50,
radius=0,
@ -292,21 +295,21 @@ class RailBullet(ba.Actor):
def handlemessage(self, msg: Any) -> Any:
super().handlemessage(msg)
if isinstance(msg, ba.DieMessage):
if isinstance(msg, bs.DieMessage):
if self.node:
self.node.delete()
elif isinstance(msg, ba.OutOfBoundsMessage):
self.handlemessage(ba.DieMessage())
elif isinstance(msg, bs.OutOfBoundsMessage):
self.handlemessage(bs.DieMessage())
# ------------------Railgun-------------------------
class Player(ba.Player['Team']):
class Player(bs.Player['Team']):
"""Our player"""
class Team(ba.Team[Player]):
class Team(bs.Team[Player]):
"""Our team"""
def __init__(self) -> None:
@ -326,91 +329,91 @@ class ObstaclesForm(enum.Enum):
RANDOM = 2
# ba_meta export game
class QuakeGame(ba.TeamGameActivity[Player, Team]):
# ba_meta export bascenev1.GameActivity
class QuakeGame(bs.TeamGameActivity[Player, Team]):
"""Quake Team Game Activity"""
name = 'Quake'
description = 'Kill a set number of enemies to win.'
available_settings = [
ba.IntSetting(
bs.IntSetting(
'Kills to Win Per Player',
default=15,
min_value=1,
increment=1,
),
ba.IntChoiceSetting(
bs.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(
bs.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(
bs.BoolSetting(
'Speed',
default=True,
),
ba.BoolSetting(
bs.BoolSetting(
'Enable Jump',
default=True,
),
ba.BoolSetting(
bs.BoolSetting(
'Enable Pickup',
default=True,
),
ba.BoolSetting(
bs.BoolSetting(
'Enable Bomb',
default=False,
),
ba.BoolSetting(
bs.BoolSetting(
'Obstacles',
default=True,
),
ba.IntChoiceSetting(
bs.IntChoiceSetting(
'Obstacles Form',
choices=[('Cube', ObstaclesForm.CUBE.value),
('Sphere', ObstaclesForm.SPHERE.value),
('Random', ObstaclesForm.RANDOM.value)],
default=0,
),
ba.IntChoiceSetting(
bs.IntChoiceSetting(
'Weapon Type',
choices=[('Rocket', WeaponType.ROCKET.value),
('Railgun', WeaponType.RAILGUN.value)],
default=WeaponType.ROCKET.value,
),
ba.BoolSetting(
bs.BoolSetting(
'Obstacles Mirror Shots',
default=False,
),
ba.IntSetting(
bs.IntSetting(
'Obstacles Count',
default=16,
min_value=0,
increment=2,
),
ba.BoolSetting(
bs.BoolSetting(
'Random Obstacles Color',
default=True,
),
ba.BoolSetting(
bs.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)
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
return issubclass(sessiontype, bs.MultiTeamSession) or issubclass(
sessiontype, bs.FreeForAllSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
# TODO add more maps
return ['Football Stadium', 'Monkey Face', 'Doom Shroom']
@ -426,15 +429,15 @@ class QuakeGame(ba.TeamGameActivity[Player, Team]):
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.default_music = (bs.MusicType.EPIC
if self._epic_mode else bs.MusicType.GRAND_ROMP)
self.slow_motion = self._epic_mode
self.announce_player_deaths = True
self._scoreboard = Scoreboard()
self._ding_sound = ba.getsound('dingSmall')
self._ding_sound = bs.getsound('dingSmall')
self._shield_dropper: Optional[ba.Timer] = None
self._shield_dropper: Optional[bs.Timer] = None
def get_instance_description(self) -> Union[str, Sequence]:
return 'Kill ${ARG1} enemies.', self._score_to_win
@ -445,11 +448,11 @@ class QuakeGame(ba.TeamGameActivity[Player, Team]):
self._update_scoreboard()
def on_begin(self) -> None:
ba.TeamGameActivity.on_begin(self)
ba.getactivity().globalsnode.tint = (0.5, 0.7, 1)
bs.TeamGameActivity.on_begin(self)
bs.getactivity().globalsnode.tint = (0.5, 0.7, 1)
self.drop_shield()
self._shield_dropper = ba.Timer(8,
ba.WeakCall(self.drop_shield),
self._shield_dropper = bs.Timer(8,
bs.WeakCall(self.drop_shield),
repeat=True)
self.setup_standard_time_limit(self._time_limit)
if self._obstacles_enabled:
@ -483,9 +486,9 @@ class QuakeGame(ba.TeamGameActivity[Player, Team]):
position=(random.uniform(-10, 10), 6,
random.uniform(-5, 5))).autoretain()
ba.playsound(self._ding_sound)
self._ding_sound.play()
p_light = ba.newnode('light',
p_light = bs.newnode('light',
owner=shield.node,
attrs={
'position': (0, 0, 0),
@ -497,7 +500,7 @@ class QuakeGame(ba.TeamGameActivity[Player, Team]):
shield.node.connectattr('position', p_light, 'position')
ba.animate(p_light, 'intensity', {0: 2, 8: 0})
bs.animate(p_light, 'intensity', {0: 2, 8: 0})
def spawn_player(self, player: Player) -> None:
spaz = self.spawn_player_spaz(player)
@ -511,7 +514,7 @@ class QuakeGame(ba.TeamGameActivity[Player, Team]):
enable_fly=False)
spaz.node.hockey = self._speed_enabled
spaz.spaz_light = ba.newnode('light',
spaz.spaz_light = bs.newnode('light',
owner=spaz.node,
attrs={
'position': (0, 0, 0),
@ -524,8 +527,8 @@ class QuakeGame(ba.TeamGameActivity[Player, Team]):
spaz.node.connectattr('position', spaz.spaz_light, 'position')
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
ba.TeamGameActivity.handlemessage(self, msg)
if isinstance(msg, bs.PlayerDiedMessage):
bs.TeamGameActivity.handlemessage(self, msg)
player = msg.getplayer(Player)
self.respawn_player(player)
killer = msg.getkillerplayer(Player)
@ -535,20 +538,20 @@ class QuakeGame(ba.TeamGameActivity[Player, Team]):
# 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):
if isinstance(self.session, bs.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)
self._ding_sound.play()
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)
self._ding_sound.play()
# in FFA show our score since its hard to find on
# the scoreboard
assert killer.actor is not None
@ -564,10 +567,10 @@ class QuakeGame(ba.TeamGameActivity[Player, Team]):
# (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)
bs.timer(0.5, self.end_game)
else:
ba.TeamGameActivity.handlemessage(self, msg)
bs.TeamGameActivity.handlemessage(self, msg)
def _update_scoreboard(self) -> None:
for team in self.teams:
@ -575,51 +578,51 @@ class QuakeGame(ba.TeamGameActivity[Player, Team]):
self._score_to_win)
def end_game(self) -> None:
results = ba.GameResults()
results = bs.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)
class Obstacle(ba.Actor):
class Obstacle(bs.Actor):
"""Scene object"""
def __init__(self,
position,
form=ObstaclesForm.CUBE,
mirror=False) -> None:
ba.Actor.__init__(self)
bs.Actor.__init__(self)
if form == ObstaclesForm.CUBE:
model = 'tnt'
mesh = 'tnt'
body = 'crate'
elif form == ObstaclesForm.SPHERE:
model = 'bomb'
mesh = 'bomb'
body = 'sphere'
else: # ObstaclesForm.RANDOM:
model = random.choice(['tnt', 'bomb'])
body = 'sphere' if model == 'bomb' else 'crate'
mesh = random.choice(['tnt', 'bomb'])
body = 'sphere' if mesh == 'bomb' else 'crate'
self.node = ba.newnode(
self.node = bs.newnode(
'prop',
delegate=self,
attrs={
'position':
position,
'model':
ba.getmodel(model),
'mesh':
bs.getmesh(mesh),
'body':
body,
'body_scale':
1.3,
'model_scale':
'mesh_scale':
1.3,
'reflection':
'powerup',
'reflection_scale': [0.7],
'color_texture':
ba.gettexture('bunnyColor'),
bs.gettexture('bunnyColor'),
'materials': [SharedObjects.get().footing_material]
if mirror else [
SharedObjects.get().object_material,
@ -628,15 +631,15 @@ class Obstacle(ba.Actor):
})
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
if isinstance(msg, bs.DieMessage):
if self.node:
self.node.delete()
elif isinstance(msg, ba.OutOfBoundsMessage):
elif isinstance(msg, bs.OutOfBoundsMessage):
if self.node:
self.handlemessage(ba.DieMessage())
self.handlemessage(bs.DieMessage())
elif isinstance(msg, ba.HitMessage):
elif isinstance(msg, bs.HitMessage):
self.node.handlemessage('impulse', msg.pos[0], msg.pos[1],
msg.pos[2], msg.velocity[0],
msg.velocity[1], msg.velocity[2],

View file

@ -1,43 +1,43 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# Released under the MIT License. See LICENSE for details.
#
"""DeathMatch game and support classes."""
# ba_meta require api 7
# ba_meta require api 8
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
import _ba
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
from bastd.gameutils import SharedObjects
from bastd.game.deathmatch import DeathMatchGame, Player, Team
from bastd.gameutils import SharedObjects
import babase
import bascenev1 as bs
from bascenev1lib.actor.playerspaz import PlayerSpaz
from bascenev1lib.gameutils import SharedObjects
from bascenev1lib.game.deathmatch import DeathMatchGame, Player
from bascenev1lib.gameutils import SharedObjects
if TYPE_CHECKING:
from typing import Any, Sequence, Dict, Type, List, Optional, Union
# ba_meta export game
# ba_meta export bascenev1.GameActivity
class ShimlaGame(DeathMatchGame):
name = 'Shimla'
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.DualTeamSession)
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
return issubclass(sessiontype, bs.DualTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
return ['Creative Thoughts']
def __init__(self, settings: dict):
super().__init__(settings)
shared = SharedObjects.get()
self.lifts = {}
self._real_wall_material = ba.Material()
self._real_wall_material = bs.Material()
self._real_wall_material.add_actions(
actions=(
@ -53,7 +53,7 @@ class ShimlaGame(DeathMatchGame):
('modify_part_collision', 'physical', True)
))
self._lift_material = ba.Material()
self._lift_material = bs.Material()
self._lift_material.add_actions(
actions=(
@ -71,14 +71,14 @@ class ShimlaGame(DeathMatchGame):
)
def on_begin(self):
ba.getactivity().globalsnode.happy_thoughts_mode = False
bs.getactivity().globalsnode.happy_thoughts_mode = False
super().on_begin()
self.make_map()
ba.timer(2, self.disable_fly)
bs.timer(2, self.disable_fly)
def disable_fly(self):
activity = _ba.get_foreground_host_activity()
activity = bs.get_foreground_host_activity()
for players in activity.players:
players.actor.node.fly = False
@ -102,29 +102,29 @@ class ShimlaGame(DeathMatchGame):
def make_map(self):
shared = SharedObjects.get()
_ba.get_foreground_host_activity()._map.leftwall.materials = [
bs.get_foreground_host_activity()._map.leftwall.materials = [
shared.footing_material, self._real_wall_material]
_ba.get_foreground_host_activity()._map.rightwall.materials = [
bs.get_foreground_host_activity()._map.rightwall.materials = [
shared.footing_material, self._real_wall_material]
_ba.get_foreground_host_activity()._map.topwall.materials = [
bs.get_foreground_host_activity()._map.topwall.materials = [
shared.footing_material, self._real_wall_material]
self.floorwall1 = ba.newnode('region', attrs={'position': (-10, 5, -5.52), 'scale':
self.floorwall1 = bs.newnode('region', attrs={'position': (-10, 5, -5.52), 'scale':
(15, 0.2, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
self.floorwall2 = ba.newnode('region', attrs={'position': (10, 5, -5.52), 'scale': (
self.floorwall2 = bs.newnode('region', attrs={'position': (10, 5, -5.52), 'scale': (
15, 0.2, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
self.wall1 = ba.newnode('region', attrs={'position': (0, 11, -6.90), 'scale': (
self.wall1 = bs.newnode('region', attrs={'position': (0, 11, -6.90), 'scale': (
35.4, 20, 1), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
self.wall2 = ba.newnode('region', attrs={'position': (0, 11, -4.14), 'scale': (
self.wall2 = bs.newnode('region', attrs={'position': (0, 11, -4.14), 'scale': (
35.4, 20, 1), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.newnode('locator', attrs={'shape': 'box', 'position': (-10, 5, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (-10, 5, -5.52), 'color': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (15, 0.2, 2)})
ba.newnode('locator', attrs={'shape': 'box', 'position': (10, 5, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (10, 5, -5.52), 'color': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (15, 0.2, 2)})
self.create_lift(-16.65, 8)
@ -151,32 +151,32 @@ class ShimlaGame(DeathMatchGame):
shared = SharedObjects.get()
ba.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (5.5, 0.1, 6),
bs.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (5.5, 0.1, 6),
'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.newnode('locator', attrs={'shape': 'box', 'position': (x, y, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (x, y, -5.52), 'color': (
1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (5.5, 0.1, 2)})
def create_lift(self, x, y):
shared = SharedObjects.get()
color = (0.7, 0.6, 0.5)
floor = ba.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (
floor = bs.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (
1.8, 0.1, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material, self._lift_material]})
cleaner = ba.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (
cleaner = bs.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (
2, 0.3, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
lift = ba.newnode('locator', attrs={'shape': 'box', 'position': (
lift = bs.newnode('locator', attrs={'shape': 'box', 'position': (
x, y, -5.52), 'color': color, 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (1.8, 3.7, 2)})
_tcombine = ba.newnode('combine',
_tcombine = bs.newnode('combine',
owner=floor,
attrs={
'input0': x,
'input2': -5.5,
'size': 3
})
mnode = ba.newnode('math',
mnode = bs.newnode('math',
owner=lift,
attrs={
'input1': (0, 2, 0),
@ -184,7 +184,7 @@ class ShimlaGame(DeathMatchGame):
})
_tcombine.connectattr('output', mnode, 'input2')
_cleaner_combine = ba.newnode('combine',
_cleaner_combine = bs.newnode('combine',
owner=cleaner,
attrs={
'input1': 5.6,
@ -192,10 +192,10 @@ class ShimlaGame(DeathMatchGame):
'size': 3
})
_cleaner_combine.connectattr('output', cleaner, 'position')
ba.animate(_tcombine, 'input1', {
bs.animate(_tcombine, 'input1', {
0: 5.1,
})
ba.animate(_cleaner_combine, 'input0', {
bs.animate(_cleaner_combine, 'input0', {
0: -19 if x < 0 else 19,
})
@ -205,29 +205,29 @@ class ShimlaGame(DeathMatchGame):
"cleaner": _cleaner_combine, 'leftLift': x < 0}
def _handle_lift(self):
region = ba.getcollision().sourcenode
region = bs.getcollision().sourcenode
lift = self.lifts[region]
def clean(lift):
ba.animate(lift["cleaner"], 'input0', {
bs.animate(lift["cleaner"], 'input0', {
0: -19 if lift["leftLift"] else 19,
2: -16 if lift["leftLift"] else 16,
4.3: -19 if lift["leftLift"] else 19
})
if lift["state"] == "origin":
lift["state"] = "transition"
ba.animate(lift["lift"], 'input1', {
bs.animate(lift["lift"], 'input1', {
0: 5.1,
1.3: 5.1,
6: 5+12,
9: 5+12,
15: 5.1
})
ba.timer(16, ba.Call(lambda lift: lift.update({'state': 'end'}), lift))
ba.timer(12, ba.Call(clean, lift))
bs.timer(16, babase.Call(lambda lift: lift.update({'state': 'end'}), lift))
bs.timer(12, babase.Call(clean, lift))
def _handle_lift_disconnect(self):
region = ba.getcollision().sourcenode
region = bs.getcollision().sourcenode
lift = self.lifts[region]
if lift["state"] == 'end':
lift["state"] = "origin"
@ -236,9 +236,9 @@ class ShimlaGame(DeathMatchGame):
shared = SharedObjects.get()
for i in range(0, 21):
ba.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (0.2, 0.1, 6),
bs.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (0.2, 0.1, 6),
'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.newnode('locator', attrs={'shape': 'box', 'position': (x, y, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (x, y, -5.52), 'color': (
1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (0.2, 0.1, 2)})
if backslash:
x = x+0.1
@ -292,7 +292,7 @@ class mapdefs:
0.5245740665, 0.5245740665, 0.01941146064)
class CreativeThoughts(ba.Map):
class CreativeThoughts(bs.Map):
"""Freaking map by smoothy."""
defs = mapdefs
@ -313,26 +313,26 @@ class CreativeThoughts(ba.Map):
@classmethod
def on_preload(cls) -> Any:
data: Dict[str, Any] = {
'model': ba.getmodel('alwaysLandLevel'),
'bottom_model': ba.getmodel('alwaysLandLevelBottom'),
'bgmodel': ba.getmodel('alwaysLandBG'),
'collide_model': ba.getcollidemodel('alwaysLandLevelCollide'),
'tex': ba.gettexture('alwaysLandLevelColor'),
'bgtex': ba.gettexture('alwaysLandBGColor'),
'vr_fill_mound_model': ba.getmodel('alwaysLandVRFillMound'),
'vr_fill_mound_tex': ba.gettexture('vrFillMound')
'mesh': bs.getmesh('alwaysLandLevel'),
'bottom_mesh': bs.getmesh('alwaysLandLevelBottom'),
'bgmesh': bs.getmesh('alwaysLandBG'),
'collision_mesh': bs.getcollisionmesh('alwaysLandLevelCollide'),
'tex': bs.gettexture('alwaysLandLevelColor'),
'bgtex': bs.gettexture('alwaysLandBGColor'),
'vr_fill_mound_mesh': bs.getmesh('alwaysLandVRFillMound'),
'vr_fill_mound_tex': bs.gettexture('vrFillMound')
}
return data
@classmethod
def get_music_type(cls) -> ba.MusicType:
return ba.MusicType.FLYING
def get_music_type(cls) -> bs.MusicType:
return bs.MusicType.FLYING
def __init__(self) -> None:
super().__init__(vr_overlay_offset=(0, -3.7, 2.5))
shared = SharedObjects.get()
self._fake_wall_material = ba.Material()
self._real_wall_material = ba.Material()
self._fake_wall_material = bs.Material()
self._real_wall_material = bs.Material()
self._fake_wall_material.add_actions(
conditions=(('they_are_younger_than', 9000), 'and',
('they_have_material', shared.player_material)),
@ -348,29 +348,29 @@ class CreativeThoughts(ba.Map):
('modify_part_collision', 'physical', True)
))
self.background = ba.newnode(
self.background = bs.newnode(
'terrain',
attrs={
'model': self.preloaddata['bgmodel'],
'mesh': self.preloaddata['bgmesh'],
'lighting': False,
'background': True,
'color_texture': ba.gettexture("rampageBGColor")
'color_texture': bs.gettexture("rampageBGColor")
})
self.leftwall = ba.newnode('region', attrs={'position': (-17.75152479, 13, -5.52), 'scale': (
self.leftwall = bs.newnode('region', attrs={'position': (-17.75152479, 13, -5.52), 'scale': (
0.1, 15.5, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
self.rightwall = ba.newnode('region', attrs={'position': (17.75, 13, -5.52), 'scale': (
self.rightwall = bs.newnode('region', attrs={'position': (17.75, 13, -5.52), 'scale': (
0.1, 15.5, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
self.topwall = ba.newnode('region', attrs={'position': (0, 21.0, -5.52), 'scale': (
self.topwall = bs.newnode('region', attrs={'position': (0, 21.0, -5.52), 'scale': (
35.4, 0.2, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.newnode('locator', attrs={'shape': 'box', 'position': (-17.75152479, 13, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (-17.75152479, 13, -5.52), 'color': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (0.1, 15.5, 2)})
ba.newnode('locator', attrs={'shape': 'box', 'position': (17.75, 13, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (17.75, 13, -5.52), 'color': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (0.1, 15.5, 2)})
ba.newnode('locator', attrs={'shape': 'box', 'position': (0, 21.0, -5.52), 'color': (
bs.newnode('locator', attrs={'shape': 'box', 'position': (0, 21.0, -5.52), 'color': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (35.4, 0.2, 2)})
gnode = ba.getactivity().globalsnode
gnode = bs.getactivity().globalsnode
gnode.happy_thoughts_mode = True
gnode.shadow_offset = (0.0, 8.0, 5.0)
gnode.tint = (1.3, 1.23, 1.0)
@ -381,9 +381,9 @@ class CreativeThoughts(ba.Map):
self.is_flying = True
# throw out some tips on flying
txt = ba.newnode('text',
txt = bs.newnode('text',
attrs={
'text': ba.Lstr(resource='pressJumpToFlyText'),
'text': babase.Lstr(resource='pressJumpToFlyText'),
'scale': 1.2,
'maxwidth': 800,
'position': (0, 200),
@ -392,7 +392,7 @@ class CreativeThoughts(ba.Map):
'h_align': 'center',
'v_attach': 'bottom'
})
cmb = ba.newnode('combine',
cmb = bs.newnode('combine',
owner=txt,
attrs={
'size': 4,
@ -400,12 +400,12 @@ class CreativeThoughts(ba.Map):
'input1': 0.9,
'input2': 0.0
})
ba.animate(cmb, 'input3', {3.0: 0, 4.0: 1, 9.0: 1, 10.0: 0})
bs.animate(cmb, 'input3', {3.0: 0, 4.0: 1, 9.0: 1, 10.0: 0})
cmb.connectattr('output', txt, 'color')
ba.timer(10.0, txt.delete)
bs.timer(10.0, txt.delete)
try:
ba._map.register_map(CreativeThoughts)
bs._map.register_map(CreativeThoughts)
except:
pass

View file

@ -1,6 +1,7 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# SimonSays
# you had really better do what Simon says...
# ba_meta require api 7
# ba_meta require api 8
from __future__ import annotations
from typing import TYPE_CHECKING
@ -8,19 +9,21 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING:
from typing import Any, Union, Sequence
from ba import _gameutils
import ba
from bascenev1 import _gameutils
import babase
import bauiv1 as bui
import bascenev1 as bs
import random
class CustomText(ba.Actor):
class CustomText(bs.Actor):
"""Text that pops up above a position to denote something special.
category: Gameplay Classes
"""
def __init__(self,
text: Union[str, ba.Lstr],
text: Union[str, babase.Lstr],
position: Sequence[float] = (0.0, 0.0, 0.0),
color: Sequence[float] = (1.0, 1.0, 1.0, 1.0),
random_offset: float = 0.5,
@ -34,7 +37,7 @@ class CustomText(ba.Actor):
(0.5 - random.random()), position[1] + offset[0] +
random_offset * (0.5 - random.random()), position[2] +
offset[0] + random_offset * (0.5 - random.random()))
self.node = ba.newnode('text',
self.node = bs.newnode('text',
attrs={
'text': text,
'in_world': True,
@ -42,27 +45,27 @@ class CustomText(ba.Actor):
'flatness': 1.0,
'h_align': 'center'}, delegate=self)
lifespan = duration
ba.animate(
bs.animate(
self.node, 'scale', {
0: 0.0,
lifespan * 0.11: 0.020 * 0.7 * scale,
lifespan * 0.16: 0.013 * 0.7 * scale,
lifespan * 0.25: 0.014 * 0.7 * scale
})
self._tcombine = ba.newnode('combine',
self._tcombine = bs.newnode('combine',
owner=self.node,
attrs={
'input0': pos[0],
'input2': pos[2],
'size': 3
})
ba.animate(self._tcombine, 'input1', {
bs.animate(self._tcombine, 'input1', {
0: pos[1] + 1.5,
lifespan: pos[1] + 2.0
})
self._tcombine.connectattr('output', self.node, 'position')
# fade our opacity in/out
self._combine = ba.newnode('combine',
self._combine = bs.newnode('combine',
owner=self.node,
attrs={
'input0': color[0],
@ -71,64 +74,64 @@ class CustomText(ba.Actor):
'size': 4
})
for i in range(4):
ba.animate(
bs.animate(
self._combine, 'input' + str(i), {
0.13 * lifespan: color[i],
0.18 * lifespan: 4.0 * color[i],
0.22 * lifespan: color[i]})
ba.animate(self._combine, 'input3', {
bs.animate(self._combine, 'input3', {
0: 0,
0.1 * lifespan: color[3],
0.7 * lifespan: color[3],
lifespan: 0})
self._combine.connectattr('output', self.node, 'color')
self._die_timer = ba.Timer(
lifespan, ba.WeakCall(self.handlemessage, ba.DieMessage()))
self._die_timer = bs.Timer(
lifespan, bs.WeakCall(self.handlemessage, bs.DieMessage()))
def handlemessage(self, msg: Any) -> Any:
assert not self.expired
if isinstance(msg, ba.DieMessage):
if isinstance(msg, bs.DieMessage):
if self.node:
self.node.delete()
else:
super().handlemessage(msg)
class Player(ba.Player['Team']):
class Player(bs.Player['Team']):
"""Our player type for this game."""
def __init__(self) -> None:
self.score = 0
class Team(ba.Team[Player]):
class Team(bs.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.score = 0
# ba_meta export game
# ba_meta export bascenev1.GameActivity
class SimonSays(ba.TeamGameActivity[Player, Team]):
class SimonSays(bs.TeamGameActivity[Player, Team]):
name = "Simon Says"
description = "You have to better do what Simon says!"
@classmethod
def get_available_settings(cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
def get_available_settings(cls, sessiontype: Type[bs.Session]) -> List[babase.Setting]:
settings = [
ba.BoolSetting("Epic Mode", default=False),
ba.BoolSetting("Enable Jumping", default=False),
ba.BoolSetting("Enable Punching", default=False),
ba.BoolSetting("Enable Picking Up", default=False),
ba.IntChoiceSetting("Timer Speed",
bs.BoolSetting("Epic Mode", default=False),
bs.BoolSetting("Enable Jumping", default=False),
bs.BoolSetting("Enable Punching", default=False),
bs.BoolSetting("Enable Picking Up", default=False),
bs.IntChoiceSetting("Timer Speed",
choices=[("Snaily", 1200),
("Slow", 900),
("Normal", 655),
("Fast", 544),
("Turbo", 460)], default=655),
ba.FloatChoiceSetting("Text Duration",
bs.FloatChoiceSetting("Text Duration",
choices=[("Slow", 2.5),
("Normal", 1.5),
("Mediocre", 1.0),
@ -136,12 +139,12 @@ class SimonSays(ba.TeamGameActivity[Player, Team]):
return settings
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
return ["Courtyard"]
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.FreeForAllSession)
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
return issubclass(sessiontype, bs.FreeForAllSession)
def __init__(self, settings: dict):
super().__init__(settings)
@ -157,7 +160,7 @@ class SimonSays(ba.TeamGameActivity[Player, Team]):
self.counter_loop = None
self.time = 5000
self._r1 = 2
self.ct_text = ba.newnode('text', attrs={
self.ct_text = bs.newnode('text', attrs={
'in_world': True,
'text': '......',
'shadow': 1.0,
@ -165,44 +168,44 @@ class SimonSays(ba.TeamGameActivity[Player, Team]):
'flatness': 0.5,
'position': (-5.627144702, 3.3275475, -9.572879116),
'scale': 0.05})
self.n1 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-4, 0, -6),
self.n1 = bs.newnode('locator', attrs={'shape': 'circle', 'position': (-4, 0, -6),
'color': (1, 0, 0), 'opacity': 0.5,
'draw_beauty': True, 'additive': True})
self.n2 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, -6),
self.n2 = bs.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, -6),
'color': (0, 1, 0), 'opacity': 0.5,
'draw_beauty': True, 'additive': True})
self.n3 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (4, 0, -6),
self.n3 = bs.newnode('locator', attrs={'shape': 'circle', 'position': (4, 0, -6),
'color': (0, 0, 1), 'opacity': 0.5,
'draw_beauty': True, 'additive': True})
self.n4 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-4, 0, -2),
self.n4 = bs.newnode('locator', attrs={'shape': 'circle', 'position': (-4, 0, -2),
'color': (1, 1, 0), 'opacity': 0.5,
'draw_beauty': True, 'additive': True})
self.n5 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, -2),
self.n5 = bs.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, -2),
'color': (0, 1, 1), 'opacity': 0.5,
'draw_beauty': True, 'additive': True})
self.n6 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (4, 0, -2),
self.n6 = bs.newnode('locator', attrs={'shape': 'circle', 'position': (4, 0, -2),
'color': (1, 0, 1), 'opacity': 0.5,
'draw_beauty': True, 'additive': True})
self.n7 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-4, 0, 2),
self.n7 = bs.newnode('locator', attrs={'shape': 'circle', 'position': (-4, 0, 2),
'color': (.5, .5, .5), 'opacity': 0.5,
'draw_beauty': True, 'additive': True})
self.n8 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, 2),
self.n8 = bs.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, 2),
'color': (.5, .325, 0), 'opacity': 0.5,
'draw_beauty': True, 'additive': True})
self.n9 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (4, 0, 2),
self.n9 = bs.newnode('locator', attrs={'shape': 'circle', 'position': (4, 0, 2),
'color': (1, 1, 1), 'opacity': 0.5,
'draw_beauty': True, 'additive': True})
self.options = ["red", "green", "blue", "yellow", "teal", "purple", "gray", "orange",
"white", "top", "bottom", "middle row", "left", "right", "center column", "outside"]
self.default_music = ba.MusicType.FLAG_CATCHER
self.default_music = bs.MusicType.FLAG_CATCHER
def get_instance_description(self) -> str:
return 'Follow the commands... but only when \"Simon says!"'
def on_player_join(self, player: Player) -> None:
if self.has_begun():
ba.screenmessage(
ba.Lstr(resource='playerDelayedJoinText',
bs.broadcastmessage(
babase.Lstr(resource='playerDelayedJoinText',
subs=[('${PLAYER}', player.getname(full=True))]),
color=(0, 1, 0),)
return
@ -227,11 +230,11 @@ class SimonSays(ba.TeamGameActivity[Player, Team]):
player.score = 0
# check for immediate end if theres only 1 player
if len(self.players) == 1:
ba.timer(4000, lambda: self.check_end(), timeformat=ba.TimeFormat.MILLISECONDS)
bs.timer(4000/1000, lambda: self.check_end())
else:
ba.timer(6000, self.call_round, timeformat=ba.TimeFormat.MILLISECONDS)
bs.timer(6000/1000, self.call_round)
def spawn_player(self, player: PlayerType) -> ba.Actor:
def spawn_player(self, player: PlayerT) -> bs.Actor:
assert player
spaz = self.spawn_player_spaz(player, position=(
0 + random.uniform(-3.6, 3.6), 2.9, -2 + random.uniform(-3.6, 3.6)))
@ -291,12 +294,11 @@ class SimonSays(ba.TeamGameActivity[Player, Team]):
self.string = "0"
self.ct_text.text = self.string
self.counter_loop = None
ba.timer(1, dummy_check, timeformat=ba.TimeFormat.MILLISECONDS)
bs.timer(1/1000, dummy_check)
else:
self.ct_text.text = str(self.now)
ba.playsound(ba.getsound('tick'))
self.counter_loop = ba.Timer(self.speed, set_counter,
timeformat=ba.TimeFormat.MILLISECONDS, repeat=True)
bs.getsound('tick').play()
self.counter_loop = bs.Timer(self.speed/1000, set_counter, repeat=True)
def check_round(self) -> None:
if self.ended:
@ -307,8 +309,8 @@ class SimonSays(ba.TeamGameActivity[Player, Team]):
player.actor.node.position_center) else False
if ((self.simon and safe == False) or ((not self.simon) and safe == True)):
player.team.score = self.round_num
player.actor.handlemessage(ba.DieMessage())
ba.timer(1633, self.call_round, timeformat=ba.TimeFormat.MILLISECONDS)
player.actor.handlemessage(bs.DieMessage())
bs.timer(1633/1000, self.call_round)
def in_circle(self, pos) -> None:
circles = []
@ -349,14 +351,14 @@ class SimonSays(ba.TeamGameActivity[Player, Team]):
return circles
def handlemessage(self, msg) -> None:
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.PlayerDiedMessage):
self.check_end()
else:
super().handlemessage(msg)
def end_game(self) -> None:
self.ended = True
results = ba.GameResults()
results = bs.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)
@ -367,4 +369,4 @@ class SimonSays(ba.TeamGameActivity[Player, Team]):
if player.is_alive():
i += 1
if i <= 2:
ba.timer(0.6, lambda: self.end_game())
bs.timer(0.6, lambda: self.end_game())

View file

@ -1,3 +1,4 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# Released under the MIT License. See LICENSE for details.
# y me (: itsre3
# =>2<=
@ -5,7 +6,7 @@
#
"""Defines Race mini-game."""
# ba_meta require api 7
# ba_meta require api 8
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
@ -14,17 +15,17 @@ import random
from typing import TYPE_CHECKING
from dataclasses import dataclass
import ba
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
import babase
import bascenev1 as bs
from bascenev1lib.actor.bomb import Bomb
from bascenev1lib.actor.playerspaz import PlayerSpaz
from bascenev1lib.actor.scoreboard import Scoreboard
from bascenev1lib.gameutils import SharedObjects
if TYPE_CHECKING:
from typing import (Any, Type, Tuple, List, Sequence, Optional, Dict,
Union)
from bastd.actor.onscreentimer import OnScreenTimer
from bascenev1lib.actor.onscreentimer import OnScreenTimer
@dataclass
@ -34,7 +35,7 @@ class RaceMine:
mine: Optional[Bomb]
class RaceRegion(ba.Actor):
class RaceRegion(bs.Actor):
"""Region used to track progress during a race."""
def __init__(self, pt: Sequence[float], index: int):
@ -43,7 +44,7 @@ class RaceRegion(ba.Actor):
assert isinstance(activity, RaceGame)
self.pos = pt
self.index = index
self.node = ba.newnode(
self.node = bs.newnode(
'region',
delegate=self,
attrs={
@ -54,11 +55,11 @@ class RaceRegion(ba.Actor):
})
class Player(ba.Player['Team']):
class Player(bs.Player['Team']):
"""Our player type for this game."""
def __init__(self) -> None:
self.distance_txt: Optional[ba.Node] = None
self.distance_txt: Optional[bs.Node] = None
self.last_region = 0
self.lap = 0
self.distance = 0.0
@ -66,7 +67,7 @@ class Player(ba.Player['Team']):
self.rank: Optional[int] = None
class Team(ba.Team[Player]):
class Team(bs.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
@ -75,22 +76,22 @@ class Team(ba.Team[Player]):
self.finished = False
# ba_meta export game
class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
# ba_meta export bascenev1.GameActivity
class SleepRaceGame(bs.TeamGameActivity[Player, Team]):
"""Game of racing around a track."""
name = 'Sleep Race'
description = 'Can you run while sleeping?'
scoreconfig = ba.ScoreConfig(label='Time',
scoreconfig = bs.ScoreConfig(label='Time',
lower_is_better=True,
scoretype=ba.ScoreType.MILLISECONDS)
scoretype=bs.ScoreType.MILLISECONDS)
@classmethod
def get_available_settings(
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
cls, sessiontype: Type[bs.Session]) -> List[babase.Setting]:
settings = [
ba.IntSetting('Laps', min_value=1, default=2, increment=1),
ba.IntChoiceSetting(
bs.IntSetting('Laps', min_value=1, default=2, increment=1),
bs.IntChoiceSetting(
'Time Limit',
default=0,
choices=[
@ -102,7 +103,7 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
('20 Minutes', 1200),
],
),
ba.IntChoiceSetting(
bs.IntChoiceSetting(
'Mine Spawning',
default=4000,
choices=[
@ -112,7 +113,7 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
('2 Seconds', 2000),
],
),
ba.IntChoiceSetting(
bs.IntChoiceSetting(
'Bomb Spawning',
choices=[
('None', 0),
@ -123,7 +124,7 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
],
default=2000,
),
ba.IntChoiceSetting(
bs.IntChoiceSetting(
'Knockout Time',
choices=[
('8 Seconds', 8000),
@ -131,48 +132,48 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
],
default=5000,
),
ba.BoolSetting('Epic Mode', default=False),
ba.BoolSetting('Credits', default=True),
bs.BoolSetting('Epic Mode', default=False),
bs.BoolSetting('Credits', default=True),
]
# We have some specific settings in teams mode.
if issubclass(sessiontype, ba.DualTeamSession):
if issubclass(sessiontype, bs.DualTeamSession):
settings.append(
ba.BoolSetting('Entire Team Must Finish', default=False))
bs.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)
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
return issubclass(sessiontype, bs.MultiTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ba.getmaps('race')
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
return bs.app.classic.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._score_sound = bs.getsound('score')
self._swipsound = bs.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._nub_tex = bs.gettexture('nub')
self._beep_1_sound = bs.getsound('raceBeep1')
self._beep_2_sound = bs.getsound('raceBeep2')
self.race_region_material: Optional[bs.Material] = None
self._regions: List[RaceRegion] = []
self._team_finish_pts: Optional[int] = None
self._time_text: Optional[ba.Actor] = None
self._cd_text: Optional[ba.Actor] = None
self._time_text: Optional[bs.Actor] = None
self._cd_text: Optional[bs.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._knockout_timer: Optional[ba.Timer] = None
self._race_mine_timer: Optional[bs.Timer] = None
self._scoreboard_timer: Optional[bs.Timer] = None
self._player_order_update_timer: Optional[bs.Timer] = None
self._start_lights: Optional[List[bs.Node]] = None
self._bomb_spawn_timer: Optional[bs.Timer] = None
self._knockout_timer: Optional[bs.Timer] = None
self._laps = int(settings['Laps'])
self._entire_team_must_finish = bool(
settings.get('Entire Team Must Finish', False))
@ -185,11 +186,11 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
# Base class overrides.
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC_RACE
if self._epic_mode else ba.MusicType.RACE)
self.default_music = (bs.MusicType.EPIC_RACE
if self._epic_mode else bs.MusicType.RACE)
def get_instance_description(self) -> Union[str, Sequence]:
if (isinstance(self.session, ba.DualTeamSession)
if (isinstance(self.session, bs.DualTeamSession)
and self._entire_team_must_finish):
t_str = ' Your entire team has to finish.'
else:
@ -208,7 +209,7 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
super().on_transition_in()
shared = SharedObjects.get()
pts = self.map.get_def_points('race_point')
mat = self.race_region_material = ba.Material()
mat = self.race_region_material = bs.Material()
mat.add_actions(conditions=('they_have_material',
shared.player_material),
actions=(
@ -224,28 +225,28 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
assert isinstance(player.actor, PlayerSpaz)
assert player.actor.node
pos = player.actor.node.position
light = ba.newnode('light',
light = bs.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})
bs.timer(0.5, light.delete)
bs.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()
collision = bs.getcollision()
try:
region = collision.sourcenode.getdelegate(RaceRegion, True)
player = collision.opposingnode.getdelegate(PlayerSpaz,
True).getplayer(
Player, True)
except ba.NotFoundError:
except bs.NotFoundError:
return
last_region = player.last_region
@ -259,8 +260,8 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
if this_region > last_region + 2:
if player.is_alive():
assert player.actor
player.actor.handlemessage(ba.DieMessage())
ba.screenmessage(ba.Lstr(
player.actor.handlemessage(bs.DieMessage())
bs.broadcastmessage(babase.Lstr(
translate=('statements', 'Killing ${NAME} for'
' skipping part of the track!'),
subs=[('${NAME}', player.getname(full=True))]),
@ -279,7 +280,7 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
# 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
if isinstance(self.session, bs.DualTeamSession
) and self._entire_team_must_finish:
team.lap = min([p.lap for p in team.players])
else:
@ -290,7 +291,7 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
# In teams mode, hand out points based on the order
# players come in.
if isinstance(self.session, ba.DualTeamSession):
if isinstance(self.session, bs.DualTeamSession):
assert self._team_finish_pts is not None
if self._team_finish_pts > 0:
self.stats.player_scored(player,
@ -303,7 +304,7 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
player.finished = True
assert player.actor
player.actor.handlemessage(
ba.DieMessage(immediate=True))
bs.DieMessage(immediate=True))
# Makes sure noone behind them passes them in rank
# while finishing.
@ -311,26 +312,26 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
# If the whole team has finished the race.
if team.lap == self._laps:
ba.playsound(self._score_sound)
self._score_sound.play()
player.team.finished = True
assert self._timer is not None
elapsed = ba.time() - self._timer.getstarttime()
elapsed = bs.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)
self._swipsound.play()
# They've just finished a lap but not the race.
else:
ba.playsound(self._swipsound)
self._swipsound.play()
self._flash_player(player, 0.3)
# Print their lap number over their head.
try:
assert isinstance(player.actor, PlayerSpaz)
mathnode = ba.newnode('math',
mathnode = bs.newnode('math',
owner=player.actor.node,
attrs={
'input1': (0, 1.9, 0),
@ -338,12 +339,12 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
})
player.actor.node.connectattr(
'torso_position', mathnode, 'input2')
tstr = ba.Lstr(resource='lapNumberText',
tstr = babase.Lstr(resource='lapNumberText',
subs=[('${CURRENT}',
str(player.lap + 1)),
('${TOTAL}', str(self._laps))
])
txtnode = ba.newnode('text',
txtnode = bs.newnode('text',
owner=mathnode,
attrs={
'text': tstr,
@ -353,15 +354,15 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
'h_align': 'center'
})
mathnode.connectattr('output', txtnode, 'position')
ba.animate(txtnode, 'scale', {
bs.animate(txtnode, 'scale', {
0.0: 0,
0.2: 0.019,
2.0: 0.019,
2.2: 0
})
ba.timer(2.3, mathnode.delete)
bs.timer(2.3, mathnode.delete)
except Exception:
ba.print_exception('Error printing lap.')
babase.print_exception('Error printing lap.')
def on_team_join(self, team: Team) -> None:
self._update_scoreboard()
@ -372,9 +373,9 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
# 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)
if (isinstance(self.session, bs.DualTeamSession)
and self._entire_team_must_finish):
ba.screenmessage(ba.Lstr(
bs.broadcastmessage(babase.Lstr(
translate=('statements',
'${TEAM} is disqualified because ${PLAYER} left'),
subs=[('${TEAM}', player.team.name),
@ -383,18 +384,18 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
player.team.finished = True
player.team.time = None
player.team.lap = 0
ba.playsound(ba.getsound('boo'))
bs.getsound('boo').play()
for otherplayer in player.team.players:
otherplayer.lap = 0
otherplayer.finished = True
try:
if otherplayer.actor is not None:
otherplayer.actor.handlemessage(ba.DieMessage())
otherplayer.actor.handlemessage(bs.DieMessage())
except Exception:
ba.print_exception('Error sending DieMessage.')
babase.print_exception('Error sending DieMessage.')
# Defer so team/player lists will be updated.
ba.pushcall(self._check_end_game)
babase.pushcall(self._check_end_game)
def _update_scoreboard(self) -> None:
for team in self.teams:
@ -402,7 +403,7 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
if not distances:
teams_dist = 0.0
else:
if (isinstance(self.session, ba.DualTeamSession)
if (isinstance(self.session, bs.DualTeamSession)
and self._entire_team_must_finish):
teams_dist = min(distances)
else:
@ -415,14 +416,14 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
show_value=False)
def on_begin(self) -> None:
from bastd.actor.onscreentimer import OnScreenTimer
from bascenev1lib.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
if self._credits:
self._cd_text = ba.NodeActor(
ba.newnode('text',
self._cd_text = bs.NodeActor(
bs.newnode('text',
attrs={
'position': (0, 0),
'h_attach': 'center',
@ -437,8 +438,8 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
}))
# Throw a timer up on-screen.
self._time_text = ba.NodeActor(
ba.newnode('text',
self._time_text = bs.NodeActor(
bs.newnode('text',
attrs={
'v_attach': 'top',
'h_attach': 'center',
@ -458,14 +459,14 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
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._race_mine_timer = bs.Timer(0.001 * self._mine_spawning,
self._update_race_mine,
repeat=True)
self._scoreboard_timer = ba.Timer(0.25,
self._scoreboard_timer = bs.Timer(0.25,
self._update_scoreboard,
repeat=True)
self._player_order_update_timer = ba.Timer(0.25,
self._player_order_update_timer = bs.Timer(0.25,
self._update_player_order,
repeat=True)
@ -478,30 +479,30 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
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)
bs.timer(lstart, self._do_light_1)
bs.timer(lstart + inc, self._do_light_2)
bs.timer(lstart + 2 * inc, self._do_light_3)
bs.timer(lstart + 3 * inc, self._start_race)
self._start_lights = []
for i in range(4):
lnub = ba.newnode('image',
lnub = bs.newnode('image',
attrs={
'texture': ba.gettexture('nub'),
'texture': bs.gettexture('nub'),
'opacity': 1.0,
'absolute_scale': True,
'position': (-75 + i * 50, light_y),
'scale': (50, 50),
'attach': 'center'
})
ba.animate(
bs.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)
bs.timer(13.0 * t_scale, lnub.delete)
self._start_lights.append(lnub)
self._start_lights[0].color = (0.2, 0, 0)
@ -512,45 +513,45 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
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)
self._beep_1_sound.play()
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)
self._beep_1_sound.play()
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)
self._beep_1_sound.play()
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)
self._beep_2_sound.play()
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.')
babase.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._bomb_spawn_timer = bs.Timer(0.001 * self._bomb_spawning,
self._spawn_bomb,
repeat=True)
def knock_players():
activity = _ba.get_foreground_host_activity()
gnode = ba.getactivity().globalsnode
activity = bs.get_foreground_host_activity()
gnode = bs.getactivity().globalsnode
for players in activity.players:
gnode.tint = (0.5, 0.5, 0.5)
node = players.actor.node
node.handlemessage('knockout', 600.0)
self.text_offset = ba.newnode('math',
self.text_offset = bs.newnode('math',
owner=node,
attrs={'input1': (-0.5, 0.5, 0.25),
'operation': 'add'})
@ -558,7 +559,7 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
'torso_position',
self.text_offset,
'input2')
self.text = ba.newnode('text',
self.text = bs.newnode('text',
owner=node,
attrs={
'h_align': 'right',
@ -571,12 +572,12 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
'output',
self.text,
'position')
ba.animate(self.text, 'scale', {0: 0.0, 1.0: 0.01})
ba.timer(2, self.text.delete)
bs.animate(self.text, 'scale', {0: 0.0, 1.0: 0.01})
bs.timer(2, self.text.delete)
if self._knockout_time != 0:
knock_time = 0.001 * self._knockout_time
self._knockout_timer = ba.Timer(knock_time,
self._knockout_timer = bs.Timer(knock_time,
knock_players,
repeat=True)
@ -586,18 +587,18 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
# Calc all player distances.
for player in self.players:
pos: Optional[ba.Vec3]
pos: Optional[babase.Vec3]
try:
pos = player.position
except ba.NotFoundError:
except bs.NotFoundError:
pos = None
if pos is not None:
r_index = player.last_region
rg1 = self._regions[r_index]
r1pt = ba.Vec3(rg1.pos[:3])
r1pt = babase.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])
r2pt = babase.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))
@ -628,8 +629,8 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
(-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))
bs.timer(random.uniform(0.0, 2.0),
bs.WeakCall(self._spawn_bomb_at_pos, pos))
def _spawn_bomb_at_pos(self, pos: Sequence[float]) -> None:
if self.has_ended():
@ -645,15 +646,15 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
def _flash_mine(self, i: int) -> None:
assert self._race_mines is not None
rmine = self._race_mines[i]
light = ba.newnode('light',
light = bs.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)
bs.animate(light, 'intensity', {0.0: 0, 0.1: 1.0, 0.2: 0}, loop=True)
bs.timer(1.0, light.delete)
def _update_race_mine(self) -> None:
assert self._race_mines is not None
@ -667,9 +668,9 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
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))
bs.timer(0.95, babase.Call(self._make_mine, m_index))
def spawn_player(self, player: Player) -> ba.Actor:
def spawn_player(self, player: Player) -> bs.Actor:
if player.team.finished:
# FIXME: This is not type-safe!
# This call is expected to always return an Actor!
@ -692,7 +693,7 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
# Prevent controlling of characters before the start of the race.
if not self._race_started:
spaz.disconnect_controls_from_player()
mathnode = ba.newnode('math',
mathnode = bs.newnode('math',
owner=spaz.node,
attrs={
'input1': (0, 1.4, 0),
@ -700,7 +701,7 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
})
spaz.node.connectattr('torso_position', mathnode, 'input2')
distance_txt = ba.newnode('text',
distance_txt = bs.newnode('text',
owner=spaz.node,
attrs={
'text': '',
@ -730,14 +731,14 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
# 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):
if isinstance(session, bs.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)
assert isinstance(session, bs.FreeForAllSession)
points_to_award = len(session.get_ffa_point_awards())
if teams_completed >= points_to_award - teams_completed:
self.end_game()
@ -754,7 +755,7 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
endtime=None if self._last_team_time is None else (
self._timer.getstarttime() + self._last_team_time))
results = ba.GameResults()
results = bs.GameResults()
for team in self.teams:
if team.time is not None:
@ -768,10 +769,10 @@ class SleepRaceGame(ba.TeamGameActivity[Player, Team]):
# odd to be announcing that now.
self.end(results=results,
announce_winning_team=isinstance(self.session,
ba.DualTeamSession))
bs.DualTeamSession))
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.PlayerDiedMessage):
# Augment default behavior.
super().handlemessage(msg)
player = msg.getplayer(Player)

View file

@ -1,19 +1,22 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# snake
# Released under the MIT License. See LICENSE for details.
#
"""Snake game by SEBASTIAN2059"""
# ba_meta require api 7
# ba_meta require api 8
# (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 import bomb as stdbomb
import babase
import bauiv1 as bui
import bascenev1 as bs
from bascenev1lib.actor.playerspaz import PlayerSpaz
from bascenev1lib.actor.scoreboard import Scoreboard
from bascenev1lib.actor import bomb as stdbomb
if TYPE_CHECKING:
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
@ -29,7 +32,7 @@ class ScoreMessage:
return self.player
class Player(ba.Player['Team']):
class Player(bs.Player['Team']):
"""Our player type for this game."""
def __init__(self) -> None:
@ -38,14 +41,14 @@ class Player(ba.Player['Team']):
self.actived = None
class Team(ba.Team[Player]):
class Team(bs.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.score = 0
lang = ba.app.lang.language
lang = bs.app.lang.language
if lang == 'Spanish':
description = 'Sobrevive a un número determinado de minas para ganar.'
join_description = 'Corre y no te dejes matar.'
@ -65,15 +68,15 @@ class Custom_Mine(stdbomb.Bomb):
source_player=source_player)
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.HitMessage):
if isinstance(msg, bs.HitMessage):
return
else:
super().handlemessage(msg)
# ba_meta export game
# ba_meta export bascenev1.GameActivity
class SnakeGame(ba.TeamGameActivity[Player, Team]):
class SnakeGame(bs.TeamGameActivity[Player, Team]):
"""A game type based on acquiring kills."""
name = 'Snake'
@ -84,15 +87,15 @@ class SnakeGame(ba.TeamGameActivity[Player, Team]):
@classmethod
def get_available_settings(
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
cls, sessiontype: Type[bs.Session]) -> List[babase.Setting]:
settings = [
ba.IntSetting(
bs.IntSetting(
'Score to Win',
min_value=40,
default=80,
increment=5,
),
ba.IntChoiceSetting(
bs.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
@ -104,7 +107,7 @@ class SnakeGame(ba.TeamGameActivity[Player, Team]):
],
default=0,
),
ba.FloatChoiceSetting(
bs.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
@ -115,27 +118,27 @@ class SnakeGame(ba.TeamGameActivity[Player, Team]):
],
default=1.0,
),
ba.BoolSetting('Epic Mode', default=False),
bs.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))
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
return (issubclass(sessiontype, bs.DualTeamSession)
or issubclass(sessiontype, bs.FreeForAllSession))
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ba.getmaps('melee')
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
return bs.app.classic.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._dingsound = bs.getsound('dingSmall')
self._beep_1_sound = ba.getsound('raceBeep1')
self._beep_2_sound = ba.getsound('raceBeep2')
self._beep_1_sound = bs.getsound('raceBeep1')
self._beep_2_sound = bs.getsound('raceBeep2')
self._epic_mode = bool(settings['Epic Mode'])
self._kills_to_win_per_player = int(
@ -146,8 +149,8 @@ class SnakeGame(ba.TeamGameActivity[Player, Team]):
# 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.default_music = (bs.MusicType.EPIC if self._epic_mode else
bs.MusicType.TO_THE_DEATH)
def get_instance_description(self) -> Union[str, Sequence]:
return join_description
@ -178,30 +181,30 @@ class SnakeGame(ba.TeamGameActivity[Player, Team]):
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)
bs.timer(lstart, self._do_light_1)
bs.timer(lstart + inc, self._do_light_2)
bs.timer(lstart + 2 * inc, self._do_light_3)
bs.timer(lstart + 3 * inc, self._start_race)
self._start_lights = []
for i in range(4):
lnub = ba.newnode('image',
lnub = bs.newnode('image',
attrs={
'texture': ba.gettexture('nub'),
'texture': bs.gettexture('nub'),
'opacity': 1.0,
'absolute_scale': True,
'position': (-75 + i * 50, light_y),
'scale': (50, 50),
'attach': 'center'
})
ba.animate(
bs.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)
bs.timer(13.0 * t_scale, lnub.delete)
self._start_lights.append(lnub)
self._start_lights[0].color = (0.2, 0, 0)
@ -212,22 +215,22 @@ class SnakeGame(ba.TeamGameActivity[Player, Team]):
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)
self._beep_1_sound.play()
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)
self._beep_1_sound.play()
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)
self._beep_1_sound.play()
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)
self._beep_2_sound.play()
self._started = True
@ -235,7 +238,7 @@ class SnakeGame(ba.TeamGameActivity[Player, Team]):
self.generate_mines(player)
# overriding the default character spawning..
def spawn_player(self, player: Player) -> ba.Actor:
def spawn_player(self, player: Player) -> bs.Actor:
spaz = self.spawn_player_spaz(player)
# Let's reconnect this player's controls to this
@ -252,7 +255,7 @@ class SnakeGame(ba.TeamGameActivity[Player, Team]):
def generate_mines(self, player: Player):
try:
player.actived = ba.Timer(0.5, ba.Call(self.spawn_mine, player), repeat=True)
player.actived = bs.Timer(0.5, babase.Call(self.spawn_mine, player), repeat=True)
except Exception as e:
print('Exception -> ' + str(e))
@ -271,7 +274,7 @@ class SnakeGame(ba.TeamGameActivity[Player, Team]):
def arm():
mine.arm()
ba.timer(0.5, arm)
bs.timer(0.5, arm)
player.mines.append(mine)
if len(player.mines) > 15:
@ -286,7 +289,7 @@ class SnakeGame(ba.TeamGameActivity[Player, Team]):
self.handlemessage(ScoreMessage(player))
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.PlayerDiedMessage):
# Augment standard behavior.
super().handlemessage(msg)
@ -304,7 +307,7 @@ class SnakeGame(ba.TeamGameActivity[Player, Team]):
assert self._score_to_win is not None
if any(team.score >= self._score_to_win for team in self.teams):
self.end_game() # ba.timer(0.5, self.end_game)
self.end_game() # bs.timer(0.5, self.end_game)
else:
return super().handlemessage(msg)
return None
@ -315,7 +318,7 @@ class SnakeGame(ba.TeamGameActivity[Player, Team]):
self._score_to_win)
def end_game(self) -> None:
results = ba.GameResults()
results = bs.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)

View file

@ -1,8 +1,9 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# Released under the MIT License. See LICENSE for details.
#
"""Defines Race mini-game."""
# ba_meta require api 7
# ba_meta require api 8
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
@ -11,16 +12,18 @@ import random
from typing import TYPE_CHECKING
from dataclasses import dataclass
import ba
from bastd.actor.bomb import Bomb, Blast, ExplodeHitMessage
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
from bastd.gameutils import SharedObjects
import babase
import bauiv1 as bui
import bascenev1 as bs
from bascenev1lib.actor.bomb import Bomb, Blast, ExplodeHitMessage
from bascenev1lib.actor.playerspaz import PlayerSpaz
from bascenev1lib.actor.scoreboard import Scoreboard
from bascenev1lib.gameutils import SharedObjects
if TYPE_CHECKING:
from typing import (Any, Type, Tuple, List, Sequence, Optional, Dict,
Union)
from bastd.actor.onscreentimer import OnScreenTimer
from bascenev1lib.actor.onscreentimer import OnScreenTimer
class NewBlast(Blast):
@ -38,7 +41,7 @@ class RaceMine:
mine: Optional[Bomb]
class RaceRegion(ba.Actor):
class RaceRegion(bs.Actor):
"""Region used to track progress during a race."""
def __init__(self, pt: Sequence[float], index: int):
@ -47,7 +50,7 @@ class RaceRegion(ba.Actor):
assert isinstance(activity, RaceGame)
self.pos = pt
self.index = index
self.node = ba.newnode(
self.node = bs.newnode(
'region',
delegate=self,
attrs={
@ -58,11 +61,11 @@ class RaceRegion(ba.Actor):
})
class Player(ba.Player['Team']):
class Player(bs.Player['Team']):
"""Our player type for this game."""
def __init__(self) -> None:
self.distance_txt: Optional[ba.Node] = None
self.distance_txt: Optional[bs.Node] = None
self.last_region = 0
self.lap = 0
self.distance = 0.0
@ -70,7 +73,7 @@ class Player(ba.Player['Team']):
self.rank: Optional[int] = None
class Team(ba.Team[Player]):
class Team(bs.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
@ -79,22 +82,22 @@ class Team(ba.Team[Player]):
self.finished = False
# ba_meta export game
class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
# ba_meta export bascenev1.GameActivity
class SquidRaceGame(bs.TeamGameActivity[Player, Team]):
"""Game of racing around a track."""
name = 'Squid Race'
description = 'Run real fast!'
scoreconfig = ba.ScoreConfig(label='Time',
scoreconfig = bs.ScoreConfig(label='Time',
lower_is_better=True,
scoretype=ba.ScoreType.MILLISECONDS)
scoretype=bs.ScoreType.MILLISECONDS)
@classmethod
def get_available_settings(
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
cls, sessiontype: Type[bs.Session]) -> List[babase.Setting]:
settings = [
ba.IntSetting('Laps', min_value=1, default=3, increment=1),
ba.IntChoiceSetting(
bs.IntSetting('Laps', min_value=1, default=3, increment=1),
bs.IntChoiceSetting(
'Time Limit',
default=0,
choices=[
@ -106,7 +109,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
('20 Minutes', 1200),
],
),
ba.IntChoiceSetting(
bs.IntChoiceSetting(
'Mine Spawning',
default=4000,
choices=[
@ -116,7 +119,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
('2 Seconds', 2000),
],
),
ba.IntChoiceSetting(
bs.IntChoiceSetting(
'Bomb Spawning',
choices=[
('None', 0),
@ -127,49 +130,49 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
],
default=2000,
),
ba.BoolSetting('Epic Mode', default=False),
bs.BoolSetting('Epic Mode', default=False),
]
# We have some specific settings in teams mode.
if issubclass(sessiontype, ba.DualTeamSession):
if issubclass(sessiontype, bs.DualTeamSession):
settings.append(
ba.BoolSetting('Entire Team Must Finish', default=False))
bs.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)
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
return issubclass(sessiontype, bs.MultiTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ba.getmaps('race')
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
return bs.app.classic.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._score_sound = bs.getsound('score')
self._swipsound = bs.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._nub_tex = bs.gettexture('nub')
self._beep_1_sound = bs.getsound('raceBeep1')
self._beep_2_sound = bs.getsound('raceBeep2')
self.race_region_material: Optional[bs.Material] = None
self._regions: List[RaceRegion] = []
self._team_finish_pts: Optional[int] = None
self._time_text: Optional[ba.Actor] = None
self._time_text: Optional[bs.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._squid_lights: Optional[List[ba.Node]] = None
self._race_mine_timer: Optional[bs.Timer] = None
self._scoreboard_timer: Optional[bs.Timer] = None
self._player_order_update_timer: Optional[bs.Timer] = None
self._start_lights: Optional[List[bs.Node]] = None
self._squid_lights: Optional[List[bs.Node]] = None
self._countdown_timer: int = 0
self._sq_mode: str = 'Easy'
self._tick_timer: Optional[ba.Timer] = None
self._bomb_spawn_timer: Optional[ba.Timer] = None
self._tick_timer: Optional[bs.Timer] = None
self._bomb_spawn_timer: Optional[bs.Timer] = None
self._laps = int(settings['Laps'])
self._entire_team_must_finish = bool(
settings.get('Entire Team Must Finish', False))
@ -179,25 +182,25 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
self._epic_mode = bool(settings['Epic Mode'])
self._countdownsounds = {
10: ba.getsound('announceTen'),
9: ba.getsound('announceNine'),
8: ba.getsound('announceEight'),
7: ba.getsound('announceSeven'),
6: ba.getsound('announceSix'),
5: ba.getsound('announceFive'),
4: ba.getsound('announceFour'),
3: ba.getsound('announceThree'),
2: ba.getsound('announceTwo'),
1: ba.getsound('announceOne')
10: bs.getsound('announceTen'),
9: bs.getsound('announceNine'),
8: bs.getsound('announceEight'),
7: bs.getsound('announceSeven'),
6: bs.getsound('announceSix'),
5: bs.getsound('announceFive'),
4: bs.getsound('announceFour'),
3: bs.getsound('announceThree'),
2: bs.getsound('announceTwo'),
1: bs.getsound('announceOne')
}
# Base class overrides.
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC_RACE
if self._epic_mode else ba.MusicType.RACE)
self.default_music = (bs.MusicType.EPIC_RACE
if self._epic_mode else bs.MusicType.RACE)
def get_instance_description(self) -> Union[str, Sequence]:
if (isinstance(self.session, ba.DualTeamSession)
if (isinstance(self.session, bs.DualTeamSession)
and self._entire_team_must_finish):
t_str = ' Your entire team has to finish.'
else:
@ -216,7 +219,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
super().on_transition_in()
shared = SharedObjects.get()
pts = self.map.get_def_points('race_point')
mat = self.race_region_material = ba.Material()
mat = self.race_region_material = bs.Material()
mat.add_actions(conditions=('they_have_material',
shared.player_material),
actions=(
@ -232,28 +235,28 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
assert isinstance(player.actor, PlayerSpaz)
assert player.actor.node
pos = player.actor.node.position
light = ba.newnode('light',
light = bs.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})
bs.timer(0.5, light.delete)
bs.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()
collision = bs.getcollision()
try:
region = collision.sourcenode.getdelegate(RaceRegion, True)
player = collision.opposingnode.getdelegate(PlayerSpaz,
True).getplayer(
Player, True)
except ba.NotFoundError:
except bs.NotFoundError:
return
last_region = player.last_region
@ -267,8 +270,8 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
if this_region > last_region + 2:
if player.is_alive():
assert player.actor
player.actor.handlemessage(ba.DieMessage())
ba.screenmessage(ba.Lstr(
player.actor.handlemessage(bs.DieMessage())
bs.broadcastmessage(babase.Lstr(
translate=('statements', 'Killing ${NAME} for'
' skipping part of the track!'),
subs=[('${NAME}', player.getname(full=True))]),
@ -287,7 +290,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
# 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
if isinstance(self.session, bs.DualTeamSession
) and self._entire_team_must_finish:
team.lap = min([p.lap for p in team.players])
else:
@ -298,7 +301,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
# In teams mode, hand out points based on the order
# players come in.
if isinstance(self.session, ba.DualTeamSession):
if isinstance(self.session, bs.DualTeamSession):
assert self._team_finish_pts is not None
if self._team_finish_pts > 0:
self.stats.player_scored(player,
@ -311,7 +314,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
player.finished = True
assert player.actor
player.actor.handlemessage(
ba.DieMessage(immediate=True))
bs.DieMessage(immediate=True))
# Makes sure noone behind them passes them in rank
# while finishing.
@ -319,25 +322,25 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
# If the whole team has finished the race.
if team.lap == self._laps:
ba.playsound(self._score_sound)
self._score_sound.play()
player.team.finished = True
assert self._timer is not None
elapsed = ba.time() - self._timer.getstarttime()
elapsed = bs.time() - self._timer.getstarttime()
self._last_team_time = player.team.time = elapsed
# Team has yet to finish.
else:
ba.playsound(self._swipsound)
self._swipsound.play()
# They've just finished a lap but not the race.
else:
ba.playsound(self._swipsound)
self._swipsound.play()
self._flash_player(player, 0.3)
# Print their lap number over their head.
try:
assert isinstance(player.actor, PlayerSpaz)
mathnode = ba.newnode('math',
mathnode = bs.newnode('math',
owner=player.actor.node,
attrs={
'input1': (0, 1.9, 0),
@ -345,12 +348,12 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
})
player.actor.node.connectattr(
'torso_position', mathnode, 'input2')
tstr = ba.Lstr(resource='lapNumberText',
tstr = babase.Lstr(resource='lapNumberText',
subs=[('${CURRENT}',
str(player.lap + 1)),
('${TOTAL}', str(self._laps))
])
txtnode = ba.newnode('text',
txtnode = bs.newnode('text',
owner=mathnode,
attrs={
'text': tstr,
@ -360,15 +363,15 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
'h_align': 'center'
})
mathnode.connectattr('output', txtnode, 'position')
ba.animate(txtnode, 'scale', {
bs.animate(txtnode, 'scale', {
0.0: 0,
0.2: 0.019,
2.0: 0.019,
2.2: 0
})
ba.timer(2.3, mathnode.delete)
bs.timer(2.3, mathnode.delete)
except Exception:
ba.print_exception('Error printing lap.')
babase.print_exception('Error printing lap.')
def on_team_join(self, team: Team) -> None:
self._update_scoreboard()
@ -377,8 +380,8 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
# Don't allow joining after we start
# (would enable leave/rejoin tomfoolery).
if self.has_begun():
ba.screenmessage(
ba.Lstr(resource='playerDelayedJoinText',
bs.broadcastmessage(
babase.Lstr(resource='playerDelayedJoinText',
subs=[('${PLAYER}', player.getname(full=True))]),
color=(0, 1, 0),
)
@ -391,9 +394,9 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
# 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)
if (isinstance(self.session, bs.DualTeamSession)
and self._entire_team_must_finish):
ba.screenmessage(ba.Lstr(
bs.broadcastmessage(babase.Lstr(
translate=('statements',
'${TEAM} is disqualified because ${PLAYER} left'),
subs=[('${TEAM}', player.team.name),
@ -402,18 +405,18 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
player.team.finished = True
player.team.time = None
player.team.lap = 0
ba.playsound(ba.getsound('boo'))
bs.getsound('boo').play()
for otherplayer in player.team.players:
otherplayer.lap = 0
otherplayer.finished = True
try:
if otherplayer.actor is not None:
otherplayer.actor.handlemessage(ba.DieMessage())
otherplayer.actor.handlemessage(bs.DieMessage())
except Exception:
ba.print_exception('Error sending DieMessage.')
babase.print_exception('Error sending DieMessage.')
# Defer so team/player lists will be updated.
ba.pushcall(self._check_end_game)
babase.pushcall(self._check_end_game)
def _update_scoreboard(self) -> None:
for team in self.teams:
@ -421,7 +424,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
if not distances:
teams_dist = 0.0
else:
if (isinstance(self.session, ba.DualTeamSession)
if (isinstance(self.session, bs.DualTeamSession)
and self._entire_team_must_finish):
teams_dist = min(distances)
else:
@ -434,15 +437,15 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
show_value=False)
def on_begin(self) -> None:
from bastd.actor.onscreentimer import OnScreenTimer
from bascenev1lib.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',
self._time_text = bs.NodeActor(
bs.newnode('text',
attrs={
'v_attach': 'top',
'h_attach': 'center',
@ -462,14 +465,14 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
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._race_mine_timer = bs.Timer(0.001 * self._mine_spawning,
self._update_race_mine,
repeat=True)
self._scoreboard_timer = ba.Timer(0.25,
self._scoreboard_timer = bs.Timer(0.25,
self._update_scoreboard,
repeat=True)
self._player_order_update_timer = ba.Timer(0.25,
self._player_order_update_timer = bs.Timer(0.25,
self._update_player_order,
repeat=True)
@ -482,30 +485,30 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
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)
bs.timer(lstart, self._do_light_1)
bs.timer(lstart + inc, self._do_light_2)
bs.timer(lstart + 2 * inc, self._do_light_3)
bs.timer(lstart + 3 * inc, self._start_race)
self._start_lights = []
for i in range(4):
lnub = ba.newnode('image',
lnub = bs.newnode('image',
attrs={
'texture': ba.gettexture('nub'),
'texture': bs.gettexture('nub'),
'opacity': 1.0,
'absolute_scale': True,
'position': (-75 + i * 50, light_y),
'scale': (50, 50),
'attach': 'center'
})
ba.animate(
bs.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)
bs.timer(13.0 * t_scale, lnub.delete)
self._start_lights.append(lnub)
self._start_lights[0].color = (0.2, 0, 0)
@ -515,16 +518,16 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
self._squid_lights = []
for i in range(2):
lnub = ba.newnode('image',
lnub = bs.newnode('image',
attrs={
'texture': ba.gettexture('nub'),
'texture': bs.gettexture('nub'),
'opacity': 1.0,
'absolute_scale': True,
'position': (-33 + i * 65, 220),
'scale': (60, 60),
'attach': 'center'
})
ba.animate(
bs.animate(
lnub, 'opacity', {
4.0 * t_scale: 0,
5.0 * t_scale: 1.0})
@ -532,12 +535,12 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
self._squid_lights[0].color = (0.2, 0, 0)
self._squid_lights[1].color = (0.0, 0.3, 0)
ba.timer(1.0, self._check_squid_end, repeat=True)
bs.timer(1.0, self._check_squid_end, repeat=True)
self._squidgame_countdown()
def _squidgame_countdown(self) -> None:
self._countdown_timer = 80 * self._laps # 80
ba.newnode(
bs.newnode(
'image',
attrs={
'opacity': 0.7,
@ -545,8 +548,8 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
'attach': 'topCenter',
'position': (-220, -40),
'scale': (135, 45),
'texture': ba.gettexture('bar')})
ba.newnode(
'texture': bs.gettexture('bar')})
bs.newnode(
'image',
attrs={
'opacity': 1.0,
@ -554,9 +557,9 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
'attach': 'topCenter',
'position': (-220, -38),
'scale': (155, 65),
'texture': ba.gettexture('uiAtlas'),
'model_transparent': ba.getmodel('meterTransparent')})
self._sgcountdown_text = ba.newnode(
'texture': bs.gettexture('uiAtlas'),
'mesh_transparent': bs.getmesh('meterTransparent')})
self._sgcountdown_text = bs.newnode(
'text',
attrs={
'v_attach': 'top',
@ -576,14 +579,14 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
self._squid_game_all_die()
if self._countdown_timer == 20:
self._sq_mode = 'Hard'
ba.playsound(ba.getsound('alarm'))
bs.getsound('alarm').play()
if self._countdown_timer == 40:
self._sq_mode = 'Normal'
if self._countdown_timer <= 20:
self._sgcountdown_text.color = (1.2, 0.0, 0.0)
self._sgcountdown_text.scale = 1.2
if self._countdown_timer in self._countdownsounds:
ba.playsound(self._countdownsounds[self._countdown_timer])
self._countdownsounds[self._countdown_timer].play()
else:
self._sgcountdown_text.color = (1.0, 1.0, 1.0)
self._sgcountdown_text.text = str(self._countdown_timer)+"s"
@ -592,14 +595,14 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
for player in self.players:
if player.is_alive():
player.actor._cursed = True
player.actor.handlemessage(ba.DieMessage())
player.actor.handlemessage(bs.DieMessage())
NewBlast(
position=player.actor.node.position,
velocity=player.actor.node.velocity,
blast_radius=3.0,
blast_type='normal').autoretain()
player.actor.handlemessage(
ba.HitMessage(
bs.HitMessage(
pos=player.actor.node.position,
velocity=player.actor.node.velocity,
magnitude=2000,
@ -612,8 +615,8 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
def _do_ticks(self) -> None:
def do_ticks():
if self._ticks:
ba.playsound(ba.getsound('tick'))
self._tick_timer = ba.timer(1.0, do_ticks, repeat=True)
bs.getsound('tick').play()
self._tick_timer = bs.timer(1.0, do_ticks, repeat=True)
def _start_squid_game(self) -> None:
easy = [4.5, 5, 5.5, 6]
@ -623,30 +626,30 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
hard if self._sq_mode == 'Hard' else
normal if self._sq_mode == 'Normal' else easy)
# if random_number == 6:
# ba.playsound(ba.getsound('lrlg_06s'))
# bs.getsound('lrlg_06s').play()
# elif random_number == 5.5:
# ba.playsound(ba.getsound('lrlg_055s'))
# bs.getsound('lrlg_055s').play()
# elif random_number == 5:
# ba.playsound(ba.getsound('lrlg_05s'))
# bs.getsound('lrlg_05s').play()
# elif random_number == 4.5:
# ba.playsound(ba.getsound('lrlg_045s'))
# bs.getsound('lrlg_045s').play()
# elif random_number == 4:
# ba.playsound(ba.getsound('lrlg_04s'))
# bs.getsound('lrlg_04s').play()
# elif random_number == 3.5:
# ba.playsound(ba.getsound('lrlg_035s'))
# bs.getsound('lrlg_035s').play()
# elif random_number == 3:
# ba.playsound(ba.getsound('lrlg_03s'))
# bs.getsound('lrlg_03s').play()
self._squid_lights[0].color = (0.2, 0, 0)
self._squid_lights[1].color = (0.0, 1.0, 0)
self._do_delete = False
self._ticks = True
ba.timer(random_number, self._stop_squid_game)
bs.timer(random_number, self._stop_squid_game)
def _stop_squid_game(self) -> None:
self._ticks = False
self._squid_lights[0].color = (1.0, 0, 0)
self._squid_lights[1].color = (0.0, 0.3, 0)
ba.timer(0.2, self._check_delete)
bs.timer(0.2, self._check_delete)
def _check_delete(self) -> None:
for player in self.players:
@ -654,7 +657,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
player.customdata['position'] = None
player.customdata['position'] = player.actor.node.position
self._do_delete = True
ba.timer(3.0 if self._sq_mode == 'Hard' else 4.0,
bs.timer(3.0 if self._sq_mode == 'Hard' else 4.0,
self._start_squid_game)
def _start_delete(self) -> None:
@ -684,14 +687,14 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
current_posz in posz_list) or not (
current_posy in posy_list):
player.actor._cursed = True
player.actor.handlemessage(ba.DieMessage())
player.actor.handlemessage(bs.DieMessage())
NewBlast(
position=player.actor.node.position,
velocity=player.actor.node.velocity,
blast_radius=3.0,
blast_type='normal').autoretain()
player.actor.handlemessage(
ba.HitMessage(
bs.HitMessage(
pos=player.actor.node.position,
velocity=player.actor.node.velocity,
magnitude=2000,
@ -713,34 +716,34 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
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)
self._beep_1_sound.play()
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)
self._beep_1_sound.play()
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)
self._beep_1_sound.play()
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)
self._beep_2_sound.play()
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.')
babase.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._bomb_spawn_timer = bs.Timer(0.001 * self._bomb_spawning,
self._spawn_bomb,
repeat=True)
@ -748,25 +751,25 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
self._squid_lights[1].color = (0.0, 1.0, 0)
self._start_squid_game()
self._do_ticks()
ba.timer(0.2, self._start_delete, repeat=True)
ba.timer(1.0, self._update_sgcountdown, repeat=True)
bs.timer(0.2, self._start_delete, repeat=True)
bs.timer(1.0, self._update_sgcountdown, repeat=True)
def _update_player_order(self) -> None:
# Calc all player distances.
for player in self.players:
pos: Optional[ba.Vec3]
pos: Optional[babase.Vec3]
try:
pos = player.position
except ba.NotFoundError:
except bs.NotFoundError:
pos = None
if pos is not None:
r_index = player.last_region
rg1 = self._regions[r_index]
r1pt = ba.Vec3(rg1.pos[:3])
r1pt = babase.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])
r2pt = babase.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))
@ -797,8 +800,8 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
(-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))
bs.timer(random.uniform(0.0, 2.0),
bs.WeakCall(self._spawn_bomb_at_pos, pos))
def _spawn_bomb_at_pos(self, pos: Sequence[float]) -> None:
if self.has_ended():
@ -814,15 +817,15 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
def _flash_mine(self, i: int) -> None:
assert self._race_mines is not None
rmine = self._race_mines[i]
light = ba.newnode('light',
light = bs.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)
bs.animate(light, 'intensity', {0.0: 0, 0.1: 1.0, 0.2: 0}, loop=True)
bs.timer(1.0, light.delete)
def _update_race_mine(self) -> None:
assert self._race_mines is not None
@ -836,9 +839,9 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
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))
bs.timer(0.95, babase.Call(self._make_mine, m_index))
def spawn_player(self, player: Player) -> ba.Actor:
def spawn_player(self, player: Player) -> bs.Actor:
if player.team.finished:
# FIXME: This is not type-safe!
# This call is expected to always return an Actor!
@ -863,7 +866,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
if not self._race_started:
spaz.disconnect_controls_from_player()
mathnode = ba.newnode('math',
mathnode = bs.newnode('math',
owner=spaz.node,
attrs={
'input1': (0, 1.4, 0),
@ -871,7 +874,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
})
spaz.node.connectattr('torso_position', mathnode, 'input2')
distance_txt = ba.newnode('text',
distance_txt = bs.newnode('text',
owner=spaz.node,
attrs={
'text': '',
@ -902,14 +905,14 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
# 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):
if isinstance(session, bs.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)
assert isinstance(session, bs.FreeForAllSession)
points_to_award = len(session.get_ffa_point_awards())
if teams_completed >= points_to_award - teams_completed:
self.end_game()
@ -926,7 +929,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
endtime=None if self._last_team_time is None else (
self._timer.getstarttime() + self._last_team_time))
results = ba.GameResults()
results = bs.GameResults()
for team in self.teams:
if team.time is not None:
@ -940,10 +943,10 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]):
# odd to be announcing that now.
self.end(results=results,
announce_winning_team=isinstance(self.session,
ba.DualTeamSession))
bs.DualTeamSession))
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.PlayerDiedMessage):
# Augment default behavior.
super().handlemessage(msg)
else:

View file

@ -1,5 +1,6 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# ba_meta require api 7
# ba_meta require api 8
"""
TheSpazGame - Mini game where all characters looks identical , identify enemies and kill them.
Author: Mr.Smoothy
@ -12,9 +13,11 @@ from __future__ import annotations
from typing import TYPE_CHECKING
import ba
from bastd.game.elimination import EliminationGame, Player
from bastd.actor.spazfactory import SpazFactory
import babase
import bauiv1 as bui
import bascenev1 as bs
from bascenev1lib.game.elimination import EliminationGame, Player
from bascenev1lib.actor.spazfactory import SpazFactory
import random
if TYPE_CHECKING:
@ -23,14 +26,14 @@ if TYPE_CHECKING:
CHARACTER = 'Spaz'
# ba_meta export game
# ba_meta export bascenev1.GameActivity
class TheSpazGame(EliminationGame):
name = 'TheSpazGame'
description = 'Enemy Spaz AmongUs. Kill them all'
scoreconfig = ba.ScoreConfig(
label='Survived', scoretype=ba.ScoreType.SECONDS, none_is_winner=True
scoreconfig = bs.ScoreConfig(
label='Survived', scoretype=bs.ScoreType.SECONDS, none_is_winner=True
)
announce_player_deaths = False
@ -39,17 +42,17 @@ class TheSpazGame(EliminationGame):
@classmethod
def get_available_settings(
cls, sessiontype: type[ba.Session]
) -> list[ba.Setting]:
cls, sessiontype: type[bs.Session]
) -> list[babase.Setting]:
settings = [
ba.IntSetting(
bs.IntSetting(
'Lives Per Player',
default=1,
min_value=1,
max_value=10,
increment=1,
),
ba.IntChoiceSetting(
bs.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
@ -61,31 +64,31 @@ class TheSpazGame(EliminationGame):
],
default=0,
),
ba.FloatChoiceSetting(
bs.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.15)
],
default=1.0,
),
ba.BoolSetting('Epic Mode', default=False),
bs.BoolSetting('Epic Mode', default=False),
]
if issubclass(sessiontype, ba.DualTeamSession):
settings.append(ba.BoolSetting('Solo Mode', default=False))
if issubclass(sessiontype, bs.DualTeamSession):
settings.append(bs.BoolSetting('Solo Mode', default=False))
settings.append(
ba.BoolSetting('Balance Total Lives', default=False)
bs.BoolSetting('Balance Total Lives', 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
def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
return issubclass(sessiontype, bs.DualTeamSession) or issubclass(
sessiontype, bs.FreeForAllSession
)
@classmethod
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
return ba.getmaps('melee')
def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
return bs.app.classic.getmaps('melee')
def get_instance_description(self) -> str | Sequence:
return (
@ -101,7 +104,7 @@ class TheSpazGame(EliminationGame):
super().__init__(settings)
self._solo_mode = False
def spawn_player(self, player: Player) -> ba.Actor:
def spawn_player(self, player: Player) -> bs.Actor:
p = [-6, -4.3, -2.6, -0.9, 0.8, 2.5, 4.2, 5.9]
q = [-4, -2.3, -0.6, 1.1, 2.8, 4.5]

View file

@ -1,4 +1,4 @@
"""UFO Boss Fight v1.0:
"""UFO Boss Fight v2.0:
Made by Cross Joy"""
# Anyone who wanna help me in giving suggestion/ fix bugs/ by creating PR,
@ -8,21 +8,28 @@ Made by Cross Joy"""
# My Discord Id: Cross Joy#0721
# My BS Discord Server: https://discford.gg/JyBY6haARJ
# ba_meta require api 7
# ba_meta require api 8
# (see https://ballistica.net/wiki/meta-tag-system)
# ---------------------------------------
# Update v2.0
# updated to api 8
# ---------------------------------------
from __future__ import annotations
import random
from typing import TYPE_CHECKING
import ba
import _ba
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.spaz import Spaz
from bastd.actor.bomb import Blast, Bomb
from bastd.actor.onscreentimer import OnScreenTimer
from bastd.actor.spazbot import SpazBotSet, StickyBot
from bastd.gameutils import SharedObjects
import babase
import bascenev1 as bs
from bascenev1lib.actor.playerspaz import PlayerSpaz
from bascenev1lib.actor.spaz import Spaz
from bascenev1lib.actor.bomb import Blast, Bomb
from bascenev1lib.actor.onscreentimer import OnScreenTimer
from bascenev1lib.actor.spazbot import SpazBotSet, StickyBot
from bascenev1lib.gameutils import SharedObjects
if TYPE_CHECKING:
from typing import Any, Sequence, Union, Callable
@ -32,17 +39,17 @@ class UFODiedMessage:
ufo: UFO
"""The UFO that was killed."""
killerplayer: ba.Player | None
"""The ba.Player that killed it (or None)."""
killerplayer: bs.Player | None
"""The bs.Player that killed it (or None)."""
how: ba.DeathType
how: bs.DeathType
"""The particular type of death."""
def __init__(
self,
ufo: UFO,
killerplayer: ba.Player | None,
how: ba.DeathType,
killerplayer: bs.Player | None,
how: bs.DeathType,
):
"""Instantiate with given values."""
self.spazbot = ufo
@ -57,7 +64,7 @@ class RoboBot(StickyBot):
highlight = (3, 3, 3)
class UFO(ba.Actor):
class UFO(bs.Actor):
"""
New AI for Boss
"""
@ -65,7 +72,7 @@ class UFO(ba.Actor):
# pylint: disable=too-many-public-methods
# pylint: disable=too-many-locals
node: ba.Node
node: bs.Node
def __init__(self, hitpoints: int = 5000):
@ -74,32 +81,29 @@ class UFO(ba.Actor):
self.update_callback: Callable[[UFO], Any] | None = None
activity = self.activity
assert isinstance(activity, ba.GameActivity)
assert isinstance(activity, bs.GameActivity)
self.platform_material = ba.Material()
self.platform_material = bs.Material()
self.platform_material.add_actions(
conditions=('they_have_material', shared.footing_material),
actions=(
'modify_part_collision', 'collide', True))
self.ice_material = ba.Material()
self.ice_material = bs.Material()
self.ice_material.add_actions(
actions=('modify_part_collision', 'friction', 0.0))
self._player_pts: list[tuple[ba.Vec3, ba.Vec3]] | None = None
self._ufo_update_timer: ba.Timer | None = None
self.last_player_attacked_by: ba.Player | None = None
self._player_pts: list[tuple[bs.Vec3, bs.Vec3]] | None = None
self._ufo_update_timer: bs.Timer | None = None
self.last_player_attacked_by: bs.Player | None = None
self.last_attacked_time = 0.0
self.last_attacked_type: tuple[str, str] | None = None
self.to_target: ba.Vec3 = ba.Vec3(0, 0, 0)
self.to_target: bs.Vec3 = bs.Vec3(0, 0, 0)
self.dist = (0, 0, 0)
self._bots = SpazBotSet()
self.frozen = False
self.y_pos = 3
self.xz_pos = 1
self.bot_count = 3
self.bot_dur_froze = False
self.hitpoints = hitpoints
self.hitpoints_max = hitpoints
@ -108,18 +112,18 @@ class UFO(ba.Actor):
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')
self._bar_tex = self._backing_tex = bs.gettexture('bar')
self._cover_tex = bs.gettexture('uiAtlas')
self._mesh = bs.getmesh('meterTransparent')
self.bar_posx = -120
self._last_hit_time: int | None = None
self.impact_scale = 1.0
self._num_times_hit = 0
self._sucker_mat = ba.Material()
self._sucker_mat = bs.Material()
self.ufo_material = ba.Material()
self.ufo_material = bs.Material()
self.ufo_material.add_actions(
conditions=('they_have_material',
shared.player_material),
@ -135,31 +139,30 @@ class UFO(ba.Actor):
self.ufo_material)),
actions=('modify_part_collision', 'physical', False))
activity = _ba.get_foreground_host_activity()
with ba.Context(activity):
point = activity.map.get_flag_position(None)
boss_spawn_pos = (point[0], point[1] + 1, point[2])
activity = bs.get_foreground_host_activity()
point = activity.map.get_flag_position(None)
boss_spawn_pos = (point[0], point[1] + 1, point[2])
self.node = ba.newnode('prop', delegate=self, attrs={
self.node = bs.newnode('prop', delegate=self, attrs={
'position': boss_spawn_pos,
'velocity': (2, 0, 0),
'color_texture': ba.gettexture('achievementFootballShutout'),
'model': ba.getmodel('landMine'),
# 'light_model': ba.getmodel('powerupSimple'),
'model_scale': 3.3,
'color_texture': bs.gettexture('achievementFootballShutout'),
'mesh': bs.getmesh('landMine'),
# 'light_mesh': bs.getmesh('powerupSimple'),
'mesh_scale': 3.3,
'body': 'landMine',
'body_scale': 3.3,
'gravity_scale': 0.05,
'gravity_scale': 0.2,
'density': 1,
'reflection': 'soft',
'reflection_scale': [0.25],
'shadow_size': 0.1,
'max_speed': 1.5,
'is_area_of_interest':
True,
True,
'materials': [shared.footing_material, shared.object_material]})
self.holder = ba.newnode('region', attrs={
self.holder = bs.newnode('region', attrs={
'position': (
boss_spawn_pos[0], boss_spawn_pos[1] - 0.25,
boss_spawn_pos[2]),
@ -168,7 +171,7 @@ class UFO(ba.Actor):
'materials': (self.platform_material, self.ice_material,
shared.object_material)})
self.suck_anim = ba.newnode('locator',
self.suck_anim = bs.newnode('locator',
owner=self.node,
attrs={'shape': 'circleOutline',
'position': (
@ -181,7 +184,7 @@ class UFO(ba.Actor):
'additive': True})
def suck_anim():
ba.animate_array(self.suck_anim, 'position', 3,
bs.animate_array(self.suck_anim, 'position', 3,
{0: (
self.node.position[0],
self.node.position[1] - 5,
@ -194,7 +197,7 @@ class UFO(ba.Actor):
self.node.position[
2] + self.to_target.z / 2)})
self.suck_timer = ba.Timer(0.5, suck_anim, repeat=True)
self.suck_timer = bs.Timer(0.5, suck_anim, repeat=True)
self.blocks = []
@ -209,14 +212,14 @@ class UFO(ba.Actor):
))
# self.sucker = ba.newnode('region', attrs={
# self.sucker = bs.newnode('region', attrs={
# 'position': (
# boss_spawn_pos[0], boss_spawn_pos[1] - 2, boss_spawn_pos[2]),
# 'scale': [2, 10, 2],
# 'type': 'box',
# 'materials': self._sucker_mat, })
self.suck = ba.newnode('region',
self.suck = bs.newnode('region',
attrs={'position': (
boss_spawn_pos[0], boss_spawn_pos[1] - 2,
boss_spawn_pos[2]),
@ -227,69 +230,65 @@ class UFO(ba.Actor):
self.node.connectattr('position', self.holder, 'position')
self.node.connectattr('position', self.suck, 'position')
ba.animate(self.node, 'model_scale', {
bs.animate(self.node, 'mesh_scale', {
0: 0,
0.2: self.node.model_scale * 1.1,
0.26: self.node.model_scale})
0.2: self.node.mesh_scale * 1.1,
0.26: self.node.mesh_scale})
self.shield_deco = ba.newnode('shield', owner=self.node,
self.shield_deco = bs.newnode('shield', owner=self.node,
attrs={'color': (4, 4, 4),
'radius': 1.2})
self.node.connectattr('position', self.shield_deco, 'position')
self._scoreboard()
self._update()
self.drop_bomb_timer = ba.Timer(1.5, ba.Call(self._drop_bomb),
self.drop_bomb_timer = bs.Timer(1.5, bs.Call(self._drop_bomb),
repeat=True)
self.drop_bots_timer = ba.Timer(15.0, ba.Call(self._drop_bots), repeat=True)
self.drop_bots_timer = bs.Timer(15.0, bs.Call(self._drop_bots), repeat=True)
def _drop_bots(self) -> None:
p = self.node.position
if not self.frozen:
for i in range(self.bot_count):
ba.timer(
1.0 + i,
lambda: self._bots.spawn_bot(
RoboBot, pos=(self.node.position[0],
self.node.position[1] - 1,
self.node.position[2]), spawn_time=0.0
),
)
else:
self.bot_dur_froze = True
for i in range(self.bot_count):
bs.timer(
1.0 + i,
lambda: self._bots.spawn_bot(
RoboBot, pos=(self.node.position[0],
self.node.position[1] - 1,
self.node.position[2]), spawn_time=0.0
),
)
def _drop_bomb(self) -> None:
t = self.to_target
p = self.node.position
if not self.frozen:
if abs(self.dist[0]) < 2 and abs(self.dist[2]) < 2:
Bomb(position=(p[0], p[1] - 0.5, p[2]),
velocity=(t[0] * 5, 0, t[2] * 5),
bomb_type='land_mine').autoretain().arm()
elif self.hitpoints > self.hitpoints_max * 3 / 4:
Bomb(position=(p[0], p[1] - 1.5, p[2]),
velocity=(t[0] * 8, 2, t[2] * 8),
bomb_type='normal').autoretain()
elif self.hitpoints > self.hitpoints_max * 1 / 2:
Bomb(position=(p[0], p[1] - 1.5, p[2]),
velocity=(t[0] * 8, 2, t[2] * 8),
bomb_type='ice').autoretain()
if abs(self.dist[0]) < 2 and abs(self.dist[2]) < 2:
Bomb(position=(p[0], p[1] - 0.5, p[2]),
velocity=(t[0] * 5, 0, t[2] * 5),
bomb_type='land_mine').autoretain().arm()
elif self.hitpoints > self.hitpoints_max * 3 / 4:
Bomb(position=(p[0], p[1] - 1.5, p[2]),
velocity=(t[0] * 8, 2, t[2] * 8),
bomb_type='normal').autoretain()
elif self.hitpoints > self.hitpoints_max * 1 / 2:
Bomb(position=(p[0], p[1] - 1.5, p[2]),
velocity=(t[0] * 8, 2, t[2] * 8),
bomb_type='ice').autoretain()
elif self.hitpoints > self.hitpoints_max * 1 / 4:
Bomb(position=(p[0], p[1] - 1.5, p[2]),
velocity=(t[0] * 15, 2, t[2] * 15),
bomb_type='sticky').autoretain()
else:
Bomb(position=(p[0], p[1] - 1.5, p[2]),
velocity=(t[0] * 15, 2, t[2] * 15),
bomb_type='impact').autoretain()
elif self.hitpoints > self.hitpoints_max * 1 / 4:
Bomb(position=(p[0], p[1] - 1.5, p[2]),
velocity=(t[0] * 15, 2, t[2] * 15),
bomb_type='sticky').autoretain()
else:
Bomb(position=(p[0], p[1] - 1.5, p[2]),
velocity=(t[0] * 15, 2, t[2] * 15),
bomb_type='impact').autoretain()
def _levitate(self):
node = ba.getcollision().opposingnode
node = bs.getcollision().opposingnode
if node.exists():
p = node.getdelegate(Spaz, True)
def raise_player(player: ba.Player):
def raise_player(player: bs.Player):
if player.is_alive():
node = player.node
try:
@ -298,12 +297,13 @@ class UFO(ba.Actor):
node.position[2], 0, 5, 0, 3, 10, 0,
0, 0, 5, 0)
except:
pass
if not self.frozen:
for i in range(7):
ba.timer(0.05 + i / 20, ba.Call(raise_player, p))
bs.timer(0.05 + i / 20, bs.Call(raise_player, p))
def on_punched(self, damage: int) -> None:
"""Called when this spaz gets punched."""
@ -315,24 +315,22 @@ class UFO(ba.Actor):
damage = abs(msg.magnitude)
if msg.hit_type == 'explosion':
damage /= 20
else:
damage /= 5
self.hitpoints -= int(damage)
if self.hitpoints <= 0:
self.handlemessage(ba.DieMessage())
self.handlemessage(bs.DieMessage())
def _get_target_player_pt(self) -> tuple[
ba.Vec3 | None, ba.Vec3 | None]:
bs.Vec3 | None, bs.Vec3 | None]:
"""Returns the position and velocity of our target.
Both values will be None in the case of no target.
"""
assert self.node
botpt = ba.Vec3(self.node.position)
botpt = bs.Vec3(self.node.position)
closest_dist: float | None = None
closest_vel: ba.Vec3 | None = None
closest: ba.Vec3 | None = None
closest_vel: bs.Vec3 | None = None
closest: bs.Vec3 | None = None
assert self._player_pts is not None
for plpt, plvel in self._player_pts:
dist = (plpt - botpt).length()
@ -349,12 +347,12 @@ class UFO(ba.Actor):
assert closest_vel is not None
assert closest is not None
return (
ba.Vec3(closest[0], closest[1], closest[2]),
ba.Vec3(closest_vel[0], closest_vel[1], closest_vel[2]),
bs.Vec3(closest[0], closest[1], closest[2]),
bs.Vec3(closest_vel[0], closest_vel[1], closest_vel[2]),
)
return None, None
def set_player_points(self, pts: list[tuple[ba.Vec3, ba.Vec3]]) -> None:
def set_player_points(self, pts: list[tuple[bs.Vec3, bs.Vec3]]) -> None:
"""Provide the spaz-bot with the locations of its enemies."""
self._player_pts = pts
@ -368,13 +366,13 @@ class UFO(ba.Actor):
Category: Gameplay Functions
"""
lifespan = 1.0
app = ba.app
app = bs.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',
do_big = app.ui.uiscale is bs.UIScale.SMALL or app.vr_mode
txtnode = bs.newnode('text',
attrs={
'text': damage,
'in_world': True,
@ -385,7 +383,7 @@ class UFO(ba.Actor):
'scale': 0.035 if do_big else 0.03
})
# Translate upward.
tcombine = ba.newnode('combine', owner=txtnode, attrs={'size': 3})
tcombine = bs.newnode('combine', owner=txtnode, attrs={'size': 3})
tcombine.connectattr('output', txtnode, 'position')
v_vals = []
pval = 0.0
@ -397,25 +395,25 @@ class UFO(ba.Actor):
vval *= 0.5
p_start = position[0]
p_dir = direction[0]
ba.animate(tcombine, 'input0',
bs.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',
bs.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',
bs.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)
bs.animate(txtnode, 'opacity', {0.7 * lifespan: 1.0, lifespan: 0.0})
bs.timer(lifespan, txtnode.delete)
def _scoreboard(self) -> None:
self._backing = ba.NodeActor(
ba.newnode('image',
self._backing = bs.NodeActor(
bs.newnode('image',
attrs={
'position': (self.bar_posx + self._width / 2, -100),
'scale': (self._width, self._height),
@ -427,15 +425,15 @@ class UFO(ba.Actor):
'attach': 'topCenter',
'texture': self._backing_tex
}))
self._bar = ba.NodeActor(
ba.newnode('image',
self._bar = bs.NodeActor(
bs.newnode('image',
attrs={
'opacity': 1.0,
'color': (0.5, 0.5, 0.5),
'attach': 'topCenter',
'texture': self._bar_tex
}))
self._bar_scale = ba.newnode('combine',
self._bar_scale = bs.newnode('combine',
owner=self._bar.node,
attrs={
'size': 2,
@ -443,7 +441,7 @@ class UFO(ba.Actor):
'input1': self._bar_height
})
self._bar_scale.connectattr('output', self._bar.node, 'scale')
self._bar_position = ba.newnode(
self._bar_position = bs.newnode(
'combine',
owner=self._bar.node,
attrs={
@ -452,8 +450,8 @@ class UFO(ba.Actor):
'input1': -100
})
self._bar_position.connectattr('output', self._bar.node, 'position')
self._cover = ba.NodeActor(
ba.newnode('image',
self._cover = bs.NodeActor(
bs.newnode('image',
attrs={
'position': (self.bar_posx + 120, -100),
'scale':
@ -465,10 +463,10 @@ class UFO(ba.Actor):
'vr_depth': 2,
'attach': 'topCenter',
'texture': self._cover_tex,
'model_transparent': self._model
'mesh_transparent': self._mesh
}))
self._score_text = ba.NodeActor(
ba.newnode('text',
self._score_text = bs.NodeActor(
bs.newnode('text',
attrs={
'position': (self.bar_posx + 120, -100),
'h_attach': 'center',
@ -487,35 +485,36 @@ class UFO(ba.Actor):
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', {
bs.animate(self._bar_scale, 'input0', {
0.0: cur_width,
0.1: self._bar_width
})
cur_x = self._bar_position.input0
ba.animate(self._bar_position, 'input0', {
bs.animate(self._bar_position, 'input0', {
0.0: cur_x,
0.1: self.bar_posx + self._bar_width / 2
})
if self.hitpoints > self.hitpoints_max * 3 / 4:
ba.animate_array(self.shield_deco, 'color', 3,
bs.animate_array(self.shield_deco, 'color', 3,
{0: self.shield_deco.color, 0.2: (4, 4, 4)})
elif self.hitpoints > self.hitpoints_max * 1 / 2:
ba.animate_array(self.shield_deco, 'color', 3,
bs.animate_array(self.shield_deco, 'color', 3,
{0: self.shield_deco.color, 0.2: (3, 3, 5)})
self.bot_count = 4
elif self.hitpoints > self.hitpoints_max * 1 / 4:
ba.animate_array(self.shield_deco, 'color', 3,
bs.animate_array(self.shield_deco, 'color', 3,
{0: self.shield_deco.color, 0.2: (1, 5, 1)})
self.bot_count = 5
else:
ba.animate_array(self.shield_deco, 'color', 3,
bs.animate_array(self.shield_deco, 'color', 3,
{0: self.shield_deco.color, 0.2: (5, 0.2, 0.2)})
self.bot_count = 6
def update_ai(self) -> None:
"""Should be called periodically to update the spaz' AI."""
# pylint: disable=too-many-branches
@ -530,10 +529,10 @@ class UFO(ba.Actor):
return
pos = self.node.position
our_pos = ba.Vec3(pos[0], pos[1] - self.y_pos, pos[2])
our_pos = bs.Vec3(pos[0], pos[1] - 3, pos[2])
target_pt_raw: ba.Vec3 | None
target_vel: ba.Vec3 | None
target_pt_raw: bs.Vec3 | None
target_vel: bs.Vec3 | None
target_pt_raw, target_vel = self._get_target_player_pt()
@ -562,15 +561,12 @@ class UFO(ba.Actor):
setattr(self.node, 'extra_acceleration',
(0, self.to_target.y * 80 + 70,
0))
else:
elif not self.frozen:
setattr(self.node, 'velocity',
(self.to_target.x * self.xz_pos,
self.to_target.y,
self.to_target.z * self.xz_pos))
(self.to_target.x, self.to_target.y, self.to_target.z))
setattr(self.node, 'extra_acceleration',
(self.to_target.x * self.xz_pos,
self.to_target.y * 80 + 70,
self.to_target.z * self.xz_pos))
(self.to_target.x, self.to_target.y * 80 + 70,
self.to_target.z))
def on_expire(self) -> None:
super().on_expire()
@ -579,14 +575,14 @@ class UFO(ba.Actor):
# no chance of them keeping activities or other things alive.
self.update_callback = None
def animate_model(self) -> None:
def animate_mesh(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})
ba.emitfx(position=self.node.position,
# bs.animate(self.node, 'mesh_scale', {
# 0: self.node.mesh_scale,
# 0.08: self.node.mesh_scale * 0.9,
# 0.15: self.node.mesh_scale})
bs.emitfx(position=self.node.position,
velocity=self.node.velocity,
count=int(6 + random.random() * 10),
scale=0.5,
@ -597,15 +593,15 @@ class UFO(ba.Actor):
# pylint: disable=too-many-branches
assert not self.expired
if isinstance(msg, ba.HitMessage):
if isinstance(msg, bs.HitMessage):
# Don't die on punches (that's annoying).
self.animate_model()
self.animate_mesh()
if self.hitpoints != 0:
self.do_damage(msg)
# self.show_damage_msg(msg)
self._update()
elif isinstance(msg, ba.DieMessage):
elif isinstance(msg, bs.DieMessage):
if self.node:
self.hitpoints = 0
self.frozen = True
@ -629,46 +625,52 @@ class UFO(ba.Actor):
position=(p_x, p[1], p_z),
blast_radius=2.0).autoretain()
ba.timer(0 + i, ba.Call(ded_explode, i))
bs.timer(0 + i, bs.Call(ded_explode, i))
ba.timer(5, self.node.delete)
ba.timer(0.1, self.suck.delete)
ba.timer(0.1, self.suck_anim.delete)
bs.timer(5, self.node.delete)
bs.timer(0.1, self.suck.delete)
bs.timer(0.1, self.suck_anim.delete)
elif isinstance(msg, ba.OutOfBoundsMessage):
activity = _ba.get_foreground_host_activity()
elif isinstance(msg, bs.OutOfBoundsMessage):
activity = bs.get_foreground_host_activity()
try:
point = activity.map.get_flag_position(None)
boss_spawn_pos = (point[0], point[1] + 1.5, point[2])
assert self.node
self.node.position = boss_spawn_pos
except:
self.handlemessage(ba.DieMessage())
self.handlemessage(bs.DieMessage())
elif isinstance(msg, ba.FreezeMessage):
elif isinstance(msg, bs.FreezeMessage):
if not self.frozen:
self.frozen = True
self.y_pos = -1.5
self.xz_pos = 0.01
self.drop_bomb_timer = False
self.drop_bots_timer = False
setattr(self.node, 'velocity',
(0, self.to_target.y, 0))
setattr(self.node, 'extra_acceleration',
(0, 0, 0))
self.node.reflection_scale = [2]
def unfrozen():
self.frozen = False
if self.bot_dur_froze:
ba.timer(0.1, ba.Call(self._drop_bots))
self.bot_dur_froze = False
self.y_pos = 3
self.xz_pos = 1
self.drop_bomb_timer = bs.Timer(1.5,
bs.Call(self._drop_bomb),
repeat=True)
self.drop_bots_timer = bs.Timer(15.0,
bs.Call(self._drop_bots),
repeat=True)
self.node.reflection_scale = [0.25]
ba.timer(5.0, unfrozen)
bs.timer(3.0, unfrozen)
else:
super().handlemessage(msg)
class UFOSet:
"""A container/controller for one or more ba.SpazBots.
"""A container/controller for one or more bs.SpazBots.
category: Bot Classes
"""
@ -684,9 +686,9 @@ class UFOSet:
self._ufo_bot_lists: list[list[UFO]] = [
[] for _ in range(self._ufo_bot_list_count)
]
self._ufo_spawn_sound = ba.getsound('spawn')
self._ufo_spawn_sound = bs.getsound('spawn')
self._ufo_spawning_count = 0
self._ufo_bot_update_timer: ba.Timer | None = None
self._ufo_bot_update_timer: bs.Timer | None = None
self.start_moving()
def _update(self) -> None:
@ -699,18 +701,18 @@ class UFOSet:
]
except Exception:
bot_list = []
ba.print_exception(
bs.print_exception(
'Error updating bot list: '
+ str(self._ufo_bot_lists[self._ufo_bot_update_list])
)
self._bot_update_list = (
self._ufo_bot_update_list + 1
) % self._ufo_bot_list_count
self._ufo_bot_update_list + 1
) % self._ufo_bot_list_count
# Update our list of player points for the bots to use.
player_pts = []
for player in ba.getactivity().players:
assert isinstance(player, ba.Player)
for player in bs.getactivity().players:
assert isinstance(player, bs.Player)
try:
# TODO: could use abstracted player.position here so we
# don't have to assume their actor type, but we have no
@ -720,12 +722,12 @@ class UFOSet:
assert player.actor.node
player_pts.append(
(
ba.Vec3(player.actor.node.position),
ba.Vec3(player.actor.node.velocity),
bs.Vec3(player.actor.node.position),
bs.Vec3(player.actor.node.velocity),
)
)
except Exception:
ba.print_exception('Error on bot-set _update.')
bs.print_exception('Error on bot-set _update.')
for bot in bot_list:
bot.set_player_points(player_pts)
@ -733,8 +735,8 @@ class UFOSet:
def start_moving(self) -> None:
"""Start processing bot AI updates so they start doing their thing."""
self._ufo_bot_update_timer = ba.Timer(
0.05, ba.WeakCall(self._update), repeat=True
self._ufo_bot_update_timer = bs.Timer(
0.05, bs.WeakCall(self._update), repeat=True
)
def spawn_bot(
@ -745,13 +747,13 @@ class UFOSet:
on_spawn_call: Callable[[UFO], Any] | None = None,
) -> None:
"""Spawn a bot from this set."""
from bastd.actor import spawner
from bascenev1lib.actor import spawner
spawner.Spawner(
pt=pos,
spawn_time=spawn_time,
send_spawn_message=False,
spawn_callback=ba.Call(
spawn_callback=bs.Call(
self._spawn_bot, bot_type, pos, on_spawn_call
),
)
@ -764,21 +766,21 @@ class UFOSet:
on_spawn_call: Callable[[UFO], Any] | None,
) -> None:
spaz = bot_type()
ba.playsound(self._ufo_spawn_sound, position=pos)
self._ufo_spawn_sound.play(position=pos)
assert spaz.node
spaz.node.handlemessage('flash')
spaz.node.is_area_of_interest = False
spaz.handlemessage(ba.StandMessage(pos, random.uniform(0, 360)))
spaz.handlemessage(bs.StandMessage(pos, random.uniform(0, 360)))
self.add_bot(spaz)
self._ufo_spawning_count -= 1
if on_spawn_call is not None:
on_spawn_call(spaz)
def add_bot(self, bot: UFO) -> None:
"""Add a ba.SpazBot instance to the set."""
"""Add a bs.SpazBot instance to the set."""
self._ufo_bot_lists[self._ufo_bot_add_list].append(bot)
self._ufo_bot_add_list = (
self._ufo_bot_add_list + 1) % self._ufo_bot_list_count
self._ufo_bot_add_list + 1) % self._ufo_bot_list_count
def have_living_bots(self) -> bool:
"""Return whether any bots in the set are alive or spawning."""
@ -799,26 +801,26 @@ class UFOSet:
"""Immediately clear out any bots in the set."""
# Don't do this if the activity is shutting down or dead.
activity = ba.getactivity(doraise=False)
activity = bs.getactivity(doraise=False)
if activity is None or activity.expired:
return
for i, bot_list in enumerate(self._ufo_bot_lists):
for bot in bot_list:
bot.handlemessage(ba.DieMessage(immediate=True))
bot.handlemessage(bs.DieMessage(immediate=True))
self._ufo_bot_lists[i] = []
class Player(ba.Player['Team']):
class Player(bs.Player['Team']):
"""Our player type for this game."""
class Team(ba.Team[Player]):
class Team(bs.Team[Player]):
"""Our team type for this game."""
# ba_meta export game
class UFOightGame(ba.TeamGameActivity[Player, Team]):
# ba_meta export bascenev1.GameActivity
class UFOightGame(bs.TeamGameActivity[Player, Team]):
"""
A co-op game where you try to defeat UFO Boss
as fast as possible
@ -826,47 +828,49 @@ class UFOightGame(ba.TeamGameActivity[Player, Team]):
name = 'UFO Fight'
description = 'REal Boss Fight?'
scoreconfig = ba.ScoreConfig(
label='Time', scoretype=ba.ScoreType.MILLISECONDS, lower_is_better=True
scoreconfig = bs.ScoreConfig(
label='Time', scoretype=bs.ScoreType.MILLISECONDS, lower_is_better=True
)
default_music = ba.MusicType.TO_THE_DEATH
default_music = bs.MusicType.TO_THE_DEATH
@classmethod
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
# For now we're hard-coding spawn positions and whatnot
# so we need to be sure to specify that we only support
# a specific map.
return ['Football Stadium']
@classmethod
def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool:
def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
# We currently support Co-Op only.
return issubclass(sessiontype, ba.CoopSession)
return issubclass(sessiontype, bs.CoopSession)
# In the constructor we should load any media we need/etc.
# ...but not actually create anything yet.
def __init__(self, settings: dict):
super().__init__(settings)
self._winsound = ba.getsound('score')
self._winsound = bs.getsound('score')
self._won = False
self._timer: OnScreenTimer | None = None
self._bots = UFOSet()
self._preset = str(settings['preset'])
self._credit = ba.newnode('text',
attrs={
'v_attach': 'bottom',
'h_align': 'center',
'color': (0.4, 0.4, 0.4),
'flatness': 0.5,
'shadow': 0.5,
'position': (0, 20),
'scale': 0.7,
'text': 'By Cross Joy'
})
self._credit = bs.newnode('text',
attrs={
'v_attach': 'bottom',
'h_align': 'center',
'color': (0.4, 0.4, 0.4),
'flatness': 0.5,
'shadow': 0.5,
'position': (0, 20),
'scale': 0.7,
'text': 'By Cross Joy'
})
def on_transition_in(self) -> None:
super().on_transition_in()
gnode = ba.getactivity().globalsnode
gnode = bs.getactivity().globalsnode
gnode.tint = (0.42, 0.55, 0.66)
# Called when our game actually begins.
@ -874,24 +878,26 @@ class UFOightGame(ba.TeamGameActivity[Player, Team]):
super().on_begin()
self.setup_standard_powerup_drops()
# In pro mode there's no powerups.
# Make our on-screen timer and start it roughly when our bots appear.
self._timer = OnScreenTimer()
ba.timer(4.0, self._timer.start)
bs.timer(4.0, self._timer.start)
def checker():
if not self._won:
self.timer = ba.Timer(0.1, self._check_if_won, repeat=True)
self.timer = bs.Timer(0.1, self._check_if_won, repeat=True)
ba.timer(10, checker)
activity = _ba.get_foreground_host_activity()
bs.timer(10, checker)
activity = bs.get_foreground_host_activity()
point = activity.map.get_flag_position(None)
boss_spawn_pos = (point[0], point[1] + 1.5, point[2])
# Spawn some baddies.
ba.timer(
bs.timer(
1.0,
lambda: self._bots.spawn_bot(
UFO, pos=boss_spawn_pos, spawn_time=3.0
@ -915,10 +921,10 @@ class UFOightGame(ba.TeamGameActivity[Player, Team]):
def handlemessage(self, msg: Any) -> Any:
# A player has died.
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.PlayerDiedMessage):
player = msg.getplayer(Player)
self.stats.player_was_killed(player)
ba.timer(0.1, self._checkroundover)
bs.timer(0.1, self._checkroundover)
# A spaz-bot has died.
elif isinstance(msg, UFODiedMessage):
@ -926,7 +932,7 @@ class UFOightGame(ba.TeamGameActivity[Player, Team]):
# bots if we ask here (the currently-dying bot isn't officially
# marked dead yet) ..so lets push a call into the event loop to
# check once this guy has finished dying.
ba.pushcall(self._check_if_won)
bs.pushcall(self._check_if_won)
# Let the base class handle anything we don't.
else:
@ -948,20 +954,20 @@ class UFOightGame(ba.TeamGameActivity[Player, Team]):
assert self._timer is not None
self._timer.stop()
results = ba.GameResults()
results = bs.GameResults()
# If we won, set our score to the elapsed time in milliseconds.
# (there should just be 1 team here since this is co-op).
# ..if we didn't win, leave scores as default (None) which means
# we lost.
if self._won:
elapsed_time_ms = int((ba.time() - self._timer.starttime) * 1000.0)
ba.cameraflash()
ba.playsound(self._winsound)
elapsed_time_ms = int((bs.time() - self._timer.starttime) * 1000.0)
bs.cameraflash()
self._winsound.play()
for team in self.teams:
for player in team.players:
if player.actor:
player.actor.handlemessage(ba.CelebrateMessage())
player.actor.handlemessage(bs.CelebrateMessage())
results.set_team_score(team, elapsed_time_ms)
# Ends the activity.
@ -969,11 +975,11 @@ class UFOightGame(ba.TeamGameActivity[Player, Team]):
# ba_meta export plugin
class MyUFOFightLevel(ba.Plugin):
class MyUFOFightLevel(babase.Plugin):
def on_app_running(self) -> None:
ba.app.add_coop_practice_level(
ba.Level(
babase.app.classic.add_coop_practice_level(
bs.Level(
name='The UFO Fight',
displayname='${GAME}',
gametype=UFOightGame,
@ -981,3 +987,4 @@ class MyUFOFightLevel(ba.Plugin):
preview_texture_name='footballStadiumPreview',
)
)

View file

@ -1,3 +1,4 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
"""Ultimate Last Stand V2:
Made by Cross Joy"""
@ -25,7 +26,7 @@ Made by Cross Joy"""
# ----------------------------------------------------------------------------
# ba_meta require api 7
# ba_meta require api 8
from __future__ import annotations
@ -33,13 +34,15 @@ import random
from dataclasses import dataclass
from typing import TYPE_CHECKING
import ba
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.bomb import TNTSpawner
from bastd.actor.onscreentimer import OnScreenTimer
from bastd.actor.scoreboard import Scoreboard
from bastd.actor.spazfactory import SpazFactory
from bastd.actor.spazbot import (SpazBot, SpazBotSet, BomberBot,
import babase
import bauiv1 as bui
import bascenev1 as bs
from bascenev1lib.actor.playerspaz import PlayerSpaz
from bascenev1lib.actor.bomb import TNTSpawner
from bascenev1lib.actor.onscreentimer import OnScreenTimer
from bascenev1lib.actor.scoreboard import Scoreboard
from bascenev1lib.actor.spazfactory import SpazFactory
from bascenev1lib.actor.spazbot import (SpazBot, SpazBotSet, BomberBot,
BomberBotPro, BomberBotProShielded,
BrawlerBot, BrawlerBotPro,
BrawlerBotProShielded, TriggerBot,
@ -48,7 +51,7 @@ from bastd.actor.spazbot import (SpazBot, SpazBotSet, BomberBot,
if TYPE_CHECKING:
from typing import Any, Sequence
from bastd.actor.spazbot import SpazBot
from bascenev1lib.actor.spazbot import SpazBot
class IceBot(SpazBot):
@ -71,7 +74,7 @@ class IceBot(SpazBot):
points_mult = 3
class Icon(ba.Actor):
class Icon(bs.Actor):
"""Creates in in-game icon on screen."""
def __init__(self,
@ -90,10 +93,10 @@ class Icon(ba.Actor):
self._show_lives = show_lives
self._show_death = show_death
self._name_scale = name_scale
self._outline_tex = ba.gettexture('characterIconMask')
self._outline_tex = bs.gettexture('characterIconMask')
icon = player.get_icon()
self.node = ba.newnode('image',
self.node = bs.newnode('image',
delegate=self,
attrs={
'texture': icon['texture'],
@ -106,12 +109,12 @@ class Icon(ba.Actor):
'absolute_scale': True,
'attach': 'bottomCenter'
})
self._name_text = ba.newnode(
self._name_text = bs.newnode(
'text',
owner=self.node,
attrs={
'text': ba.Lstr(value=player.getname()),
'color': ba.safecolor(player.team.color),
'text': babase.Lstr(value=player.getname()),
'color': babase.safecolor(player.team.color),
'h_align': 'center',
'v_align': 'center',
'vr_depth': 410,
@ -122,7 +125,7 @@ class Icon(ba.Actor):
'v_attach': 'bottom'
})
if self._show_lives:
self._lives_text = ba.newnode('text',
self._lives_text = bs.newnode('text',
owner=self.node,
attrs={
'text': 'x0',
@ -178,7 +181,7 @@ class Icon(ba.Actor):
if not self.node:
return
if self._show_death:
ba.animate(
bs.animate(
self.node, 'opacity', {
0.00: 1.0,
0.05: 0.0,
@ -195,10 +198,10 @@ class Icon(ba.Actor):
})
lives = self._player.lives
if lives == 0:
ba.timer(0.6, self.update_for_lives)
bs.timer(0.6, self.update_for_lives)
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.DieMessage):
if isinstance(msg, bs.DieMessage):
self.node.delete()
return None
return super().handlemessage(msg)
@ -212,7 +215,7 @@ class SpawnInfo:
dincrease: float
class Player(ba.Player['Team']):
class Player(bs.Player['Team']):
"""Our player type for this game."""
def __init__(self) -> None:
@ -222,7 +225,7 @@ class Player(ba.Player['Team']):
self.icons: list[Icon] = []
class Team(ba.Team[Player]):
class Team(bs.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
@ -230,14 +233,14 @@ class Team(ba.Team[Player]):
self.spawn_order: list[Player] = []
# ba_meta export game
class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
# ba_meta export bascenev1.GameActivity
class UltimateLastStand(bs.TeamGameActivity[Player, Team]):
"""Minigame involving dodging falling bombs."""
name = 'Ultimate Last Stand'
description = 'Only the strongest will stand at the end.'
scoreconfig = ba.ScoreConfig(label='Survived',
scoretype=ba.ScoreType.SECONDS,
scoreconfig = bs.ScoreConfig(label='Survived',
scoretype=bs.ScoreType.SECONDS,
none_is_winner=True)
# Print messages when players die (since its meaningful in this game).
@ -250,16 +253,16 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
@classmethod
def get_available_settings(
cls,
sessiontype: type[ba.Session]) -> list[ba.Setting]:
sessiontype: type[bs.Session]) -> list[babase.Setting]:
settings = [
ba.IntSetting(
bs.IntSetting(
'Lives Per Player',
default=1,
min_value=1,
max_value=10,
increment=1,
),
ba.FloatChoiceSetting(
bs.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
@ -270,31 +273,31 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
],
default=1.0,
),
ba.BoolSetting('Epic Mode', default=False),
bs.BoolSetting('Epic Mode', default=False),
]
if issubclass(sessiontype, ba.DualTeamSession):
if issubclass(sessiontype, bs.DualTeamSession):
settings.append(
ba.BoolSetting('Balance Total Lives', default=False))
bs.BoolSetting('Balance Total Lives', default=False))
return settings
# We're currently hard-coded for one map.
@classmethod
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
return ['Rampage']
# We support teams, free-for-all, and co-op sessions.
@classmethod
def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool:
return (issubclass(sessiontype, ba.DualTeamSession)
or issubclass(sessiontype, ba.FreeForAllSession))
def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
return (issubclass(sessiontype, bs.DualTeamSession)
or issubclass(sessiontype, bs.FreeForAllSession))
def __init__(self, settings: dict):
super().__init__(settings)
self._scoreboard = Scoreboard()
self._start_time: float | None = None
self._vs_text: ba.Actor | None = None
self._round_end_timer: ba.Timer | None = None
self._vs_text: bs.Actor | None = None
self._round_end_timer: bs.Timer | None = None
self._lives_per_player = int(settings['Lives Per Player'])
self._balance_total_lives = bool(
settings.get('Balance Total Lives', False))
@ -302,17 +305,17 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
self._last_player_death_time: float | None = None
self._timer: OnScreenTimer | None = None
self._tntspawner: TNTSpawner | None = None
self._new_wave_sound = ba.getsound('scoreHit01')
self._new_wave_sound = bs.getsound('scoreHit01')
self._bots = SpazBotSet()
self._tntspawnpos = (0, 5.5, -6)
self.spazList = []
# Base class overrides:
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC
if self._epic_mode else ba.MusicType.SURVIVAL)
self.default_music = (bs.MusicType.EPIC
if self._epic_mode else bs.MusicType.SURVIVAL)
self.node = ba.newnode('text',
self.node = bs.newnode('text',
attrs={
'v_attach': 'bottom',
'h_align': 'center',
@ -342,24 +345,24 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
} # yapf: disable
# Some base class overrides:
self.default_music = (ba.MusicType.EPIC
if self._epic_mode else ba.MusicType.SURVIVAL)
self.default_music = (bs.MusicType.EPIC
if self._epic_mode else bs.MusicType.SURVIVAL)
if self._epic_mode:
self.slow_motion = True
def get_instance_description(self) -> str | Sequence:
return 'Only the strongest team will stand at the end.' if isinstance(
self.session,
ba.DualTeamSession) else 'Only the strongest will stand at the end.'
bs.DualTeamSession) else 'Only the strongest will stand at the end.'
def get_instance_description_short(self) -> str | Sequence:
return 'Only the strongest team will stand at the end.' if isinstance(
self.session,
ba.DualTeamSession) else 'Only the strongest will stand at the end.'
bs.DualTeamSession) else 'Only the strongest will stand at the end.'
def on_transition_in(self) -> None:
super().on_transition_in()
ba.timer(1.3, ba.Call(ba.playsound, self._new_wave_sound))
bs.timer(1.3, babase.Call(babase.playsound, self._new_wave_sound))
def on_player_join(self, player: Player) -> None:
player.lives = self._lives_per_player
@ -374,13 +377,13 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
def on_begin(self) -> None:
super().on_begin()
ba.animate_array(node=self.node, attr='color', size=3, keys={
bs.animate_array(node=self.node, attr='color', size=3, keys={
0.0: (0.5, 0.5, 0.5),
0.8: (0.83, 0.69, 0.21),
1.6: (0.5, 0.5, 0.5)
}, loop=True)
ba.timer(0.001, ba.WeakCall(self._start_bot_updates))
bs.timer(0.001, bs.WeakCall(self._start_bot_updates))
self._tntspawner = TNTSpawner(position=self._tntspawnpos,
respawn_time=10.0)
@ -389,11 +392,11 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
self.setup_standard_powerup_drops()
# Check for immediate end (if we've only got 1 player, etc).
self._start_time = ba.time()
self._start_time = bs.time()
# If balance-team-lives is on, add lives to the smaller team until
# total lives match.
if (isinstance(self.session, ba.DualTeamSession)
if (isinstance(self.session, bs.DualTeamSession)
and self._balance_total_lives and self.teams[0].players
and self.teams[1].players):
if self._get_total_team_lives(
@ -409,7 +412,7 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
lesser_team.players[add_index].lives += 1
add_index = (add_index + 1) % len(lesser_team.players)
ba.timer(1.0, self._update, repeat=True)
bs.timer(1.0, self._update, repeat=True)
self._update_icons()
# We could check game-over conditions at explicit trigger points,
@ -419,7 +422,7 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
# pylint: disable=too-many-branches
# In free-for-all mode, everyone is just lined up along the bottom.
if isinstance(self.session, ba.FreeForAllSession):
if isinstance(self.session, bs.FreeForAllSession):
count = len(self.teams)
x_offs = 85
xval = x_offs * (count - 1) * -0.5
@ -453,21 +456,21 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
# Update icons in a moment since our team will be gone from the
# list then.
ba.timer(0, self._update_icons)
bs.timer(0, self._update_icons)
# If the player to leave was the last in spawn order and had
# their final turn currently in-progress, mark the survival time
# for their team.
if self._get_total_team_lives(player.team) == 0:
assert self._start_time is not None
player.team.survival_seconds = int(ba.time() - self._start_time)
player.team.survival_seconds = int(bs.time() - self._start_time)
# A departing player may trigger game-over.
# overriding the default character spawning..
def spawn_player(self, player: Player) -> ba.Actor:
def spawn_player(self, player: Player) -> bs.Actor:
actor = self.spawn_player_spaz(player)
ba.timer(0.3, ba.Call(self._print_lives, player))
bs.timer(0.3, babase.Call(self._print_lives, player))
# If we have any icons, update their state.
for icon in player.icons:
@ -475,7 +478,7 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
return actor
def _print_lives(self, player: Player) -> None:
from bastd.actor import popuptext
from bascenev1lib.actor import popuptext
# We get called in a timer so it's possible our player has left/etc.
if not player or not player.is_alive() or not player.node:
@ -499,14 +502,14 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
self._update_bots()
if len(self.players) > 3:
self._update_bots()
self._bot_update_timer = ba.Timer(self._bot_update_interval,
ba.WeakCall(self._update_bots))
self._bot_update_timer = bs.Timer(self._bot_update_interval,
bs.WeakCall(self._update_bots))
def _update_bots(self) -> None:
assert self._bot_update_interval is not None
self._bot_update_interval = max(0.5, self._bot_update_interval * 0.98)
self._bot_update_timer = ba.Timer(self._bot_update_interval,
ba.WeakCall(self._update_bots))
self._bot_update_timer = bs.Timer(self._bot_update_interval,
bs.WeakCall(self._update_bots))
botspawnpts: list[Sequence[float]] = [[-5.0, 5.5, -4.14],
[0.0, 5.5, -4.14],
[5.0, 5.5, -4.14]]
@ -516,7 +519,7 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
assert isinstance(player.actor, PlayerSpaz)
assert player.actor.node
except Exception:
ba.print_exception('Error updating bots.')
babase.print_exception('Error updating bots.')
spawnpt = random.choice(
[botspawnpts[0], botspawnpts[1], botspawnpts[2]])
@ -550,12 +553,12 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
# Various high-level game events come through this method.
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.PlayerDiedMessage):
# Augment standard behavior.
super().handlemessage(msg)
curtime = ba.time()
curtime = bs.time()
# Record the player's moment of death.
# assert isinstance(msg.spaz.player
@ -574,14 +577,14 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
# Play big death sound on our last death
# or for every one in solo mode.
if player.lives == 0:
ba.playsound(SpazFactory.get().single_player_death_sound)
SpazFactory.get().single_player_death_sound.play()
# If we hit zero lives, we're dead (and our team might be too).
if player.lives == 0:
# If the whole team is now dead, mark their survival time.
if self._get_total_team_lives(player.team) == 0:
assert self._start_time is not None
player.team.survival_seconds = int(ba.time() -
player.team.survival_seconds = int(bs.time() -
self._start_time)
else:
# Otherwise, in regular mode, respawn.
@ -599,7 +602,7 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
# the game (allows the dust to settle and draws to occur if deaths
# are close enough).
if len(self._get_living_teams()) < 2:
self._round_end_timer = ba.Timer(0.5, self.end_game)
self._round_end_timer = bs.Timer(0.5, self.end_game)
def end_game(self) -> None:
# Stop updating our time text, and set the final time to match
@ -608,7 +611,7 @@ class UltimateLastStand(ba.TeamGameActivity[Player, Team]):
# Ok now calc game results: set a score for each team and then tell
# the game to end.
results = ba.GameResults()
results = bs.GameResults()
# Remember that 'free-for-all' mode is simply a special form
# of 'teams' mode where each player gets their own team, so we can

View file

@ -1,23 +1,26 @@
# ba_meta require api 7
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport)
# ba_meta require api 8
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
import _ba
import babase
import bauiv1 as bui
import bascenev1 as bs
import _babase
import copy
import random
from ba import _math
from ba._coopsession import CoopSession
from ba._messages import PlayerDiedMessage, StandMessage
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
from bastd.game.elimination import Icon, Player
from bastd.actor.spaz import PickupMessage
from bastd.actor.spazbot import SpazBotSet, BrawlerBot, SpazBotDiedMessage
from bastd.actor.spazfactory import SpazFactory
from babase import _math
from bascenev1._coopsession import CoopSession
from bascenev1._messages import PlayerDiedMessage, StandMessage
from bascenev1lib.actor.playerspaz import PlayerSpaz
from bascenev1lib.actor.scoreboard import Scoreboard
from bascenev1lib.game.elimination import Icon, Player
from bascenev1lib.actor.spaz import PickupMessage
from bascenev1lib.actor.spazbot import SpazBotSet, BrawlerBot, SpazBotDiedMessage
from bascenev1lib.actor.spazfactory import SpazFactory
if TYPE_CHECKING:
@ -26,7 +29,7 @@ if TYPE_CHECKING:
class PlayerSpaz_Zom(PlayerSpaz):
def handlemessage(self, m: Any) -> Any:
if isinstance(m, ba.HitMessage):
if isinstance(m, bs.HitMessage):
if not self.node:
return
if not m._source_player is None:
@ -40,7 +43,7 @@ class PlayerSpaz_Zom(PlayerSpaz):
else:
super().handlemessage(m)
elif isinstance(m, ba.FreezeMessage):
elif isinstance(m, bs.FreezeMessage):
pass
elif isinstance(m, PickupMessage):
@ -48,10 +51,10 @@ class PlayerSpaz_Zom(PlayerSpaz):
return None
try:
collision = ba.getcollision()
collision = bs.getcollision()
opposingnode = collision.opposingnode
opposingbody = collision.opposingbody
except ba.NotFoundError:
except bs.NotFoundError:
return True
try:
@ -85,7 +88,7 @@ class PlayerSpaz_Zom(PlayerSpaz):
class PlayerZombie(PlayerSpaz):
def handlemessage(self, m: Any) -> Any:
if isinstance(m, ba.HitMessage):
if isinstance(m, bs.HitMessage):
if not self.node:
return None
if not m._source_player is None:
@ -106,8 +109,8 @@ class PlayerZombie(PlayerSpaz):
class zBotSet(SpazBotSet):
def start_moving(self) -> None:
"""Start processing bot AI updates so they start doing their thing."""
self._bot_update_timer = ba.Timer(0.05,
ba.WeakCall(self.zUpdate),
self._bot_update_timer = bs.Timer(0.05,
bs.WeakCall(self.zUpdate),
repeat=True)
def zUpdate(self) -> None:
@ -118,31 +121,31 @@ class zBotSet(SpazBotSet):
])
except Exception:
bot_list = []
ba.print_exception('Error updating bot list: ' +
babase.print_exception('Error updating bot list: ' +
str(self._bot_lists[self._bot_update_list]))
self._bot_update_list = (self._bot_update_list +
1) % self._bot_list_count
player_pts = []
for player in ba.getactivity().players:
assert isinstance(player, ba.Player)
for player in bs.getactivity().players:
assert isinstance(player, bs.Player)
try:
if player.is_alive():
assert isinstance(player.actor, Spaz)
assert player.actor.node
if player.lives > 0:
player_pts.append(
(ba.Vec3(player.actor.node.position),
ba.Vec3(player.actor.node.velocity)))
(babase.Vec3(player.actor.node.position),
babase.Vec3(player.actor.node.velocity)))
except Exception:
ba.print_exception('Error on bot-set _update.')
babase.print_exception('Error on bot-set _update.')
for bot in bot_list:
bot.set_player_points(player_pts)
bot.update_ai()
class Team(ba.Team[Player]):
class Team(bs.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
@ -150,13 +153,13 @@ class Team(ba.Team[Player]):
self.spawn_order: list[Player] = []
# ba_meta export game
class ZombieHorde(ba.TeamGameActivity[Player, Team]):
# ba_meta export bascenev1.GameActivity
class ZombieHorde(bs.TeamGameActivity[Player, Team]):
name = 'Zombie Horde'
description = 'Kill walkers for points!'
scoreconfig = ba.ScoreConfig(label='Score',
scoretype=ba.ScoreType.POINTS,
scoreconfig = bs.ScoreConfig(label='Score',
scoretype=bs.ScoreType.POINTS,
none_is_winner=False,
lower_is_better=False)
# Show messages when players die since it's meaningful here.
@ -164,23 +167,23 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
@classmethod
def get_available_settings(
cls, sessiontype: type[ba.Session]) -> list[ba.Setting]:
cls, sessiontype: type[bs.Session]) -> list[babase.Setting]:
settings = [
ba.IntSetting(
bs.IntSetting(
'Lives Per Player',
default=1,
min_value=1,
max_value=10,
increment=1,
),
ba.IntSetting(
bs.IntSetting(
'Max Zombies',
default=10,
min_value=5,
max_value=50,
increment=5,
),
ba.IntChoiceSetting(
bs.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
@ -192,7 +195,7 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
],
default=0,
),
ba.FloatChoiceSetting(
bs.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
@ -203,29 +206,29 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
],
default=1.0,
),
ba.BoolSetting('Epic Mode', default=False),
bs.BoolSetting('Epic Mode', default=False),
]
if issubclass(sessiontype, ba.DualTeamSession):
settings.append(ba.BoolSetting('Solo Mode', default=False))
if issubclass(sessiontype, bs.DualTeamSession):
settings.append(bs.BoolSetting('Solo Mode', default=False))
settings.append(
ba.BoolSetting('Balance Total Lives', default=False))
bs.BoolSetting('Balance Total Lives', 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))
def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
return (issubclass(sessiontype, bs.DualTeamSession)
or issubclass(sessiontype, bs.FreeForAllSession))
@classmethod
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
return ba.getmaps('melee')
def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
return bs.app.classic.getmaps('melee')
def __init__(self, settings: dict):
super().__init__(settings)
self._scoreboard = Scoreboard()
self._start_time: float | None = None
self._vs_text: ba.Actor | None = None
self._round_end_timer: ba.Timer | None = None
self._vs_text: bs.Actor | None = None
self._round_end_timer: bs.Timer | None = None
self._epic_mode = bool(settings['Epic Mode'])
self._lives_per_player = int(settings['Lives Per Player'])
self._max_zombies = int(settings['Max Zombies'])
@ -236,53 +239,53 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
# Base class overrides:
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC
if self._epic_mode else ba.MusicType.SURVIVAL)
self.default_music = (bs.MusicType.EPIC
if self._epic_mode else bs.MusicType.SURVIVAL)
self.spazList = []
self.zombieQ = 0
activity = ba.getactivity()
activity = bs.getactivity()
my_factory = SpazFactory.get()
appears = ['Kronk', 'Zoe', 'Pixel', 'Agent Johnson',
'Bones', 'Frosty', 'Kronk2']
myAppear = copy.copy(ba.app.spaz_appearances['Kronk'])
myAppear = copy.copy(babase.app.classic.spaz_appearances['Kronk'])
myAppear.name = 'Kronk2'
ba.app.spaz_appearances['Kronk2'] = myAppear
babase.app.classic.spaz_appearances['Kronk2'] = myAppear
for appear in appears:
my_factory.get_media(appear)
med = my_factory.spaz_media
med['Kronk2']['head_model'] = med['Zoe']['head_model']
med['Kronk2']['head_mesh'] = med['Zoe']['head_mesh']
med['Kronk2']['color_texture'] = med['Agent Johnson']['color_texture']
med['Kronk2']['color_mask_texture'] = med['Pixel']['color_mask_texture']
med['Kronk2']['torso_model'] = med['Bones']['torso_model']
med['Kronk2']['pelvis_model'] = med['Pixel']['pelvis_model']
med['Kronk2']['upper_arm_model'] = med['Frosty']['upper_arm_model']
med['Kronk2']['forearm_model'] = med['Frosty']['forearm_model']
med['Kronk2']['hand_model'] = med['Bones']['hand_model']
med['Kronk2']['upper_leg_model'] = med['Bones']['upper_leg_model']
med['Kronk2']['lower_leg_model'] = med['Pixel']['lower_leg_model']
med['Kronk2']['toes_model'] = med['Bones']['toes_model']
med['Kronk2']['torso_mesh'] = med['Bones']['torso_mesh']
med['Kronk2']['pelvis_mesh'] = med['Pixel']['pelvis_mesh']
med['Kronk2']['upper_arm_mesh'] = med['Frosty']['upper_arm_mesh']
med['Kronk2']['forearm_mesh'] = med['Frosty']['forearm_mesh']
med['Kronk2']['hand_mesh'] = med['Bones']['hand_mesh']
med['Kronk2']['upper_leg_mesh'] = med['Bones']['upper_leg_mesh']
med['Kronk2']['lower_leg_mesh'] = med['Pixel']['lower_leg_mesh']
med['Kronk2']['toes_mesh'] = med['Bones']['toes_mesh']
def get_instance_description(self) -> str | Sequence:
return ('Kill walkers for points! ',
'Dead player walker: 2 points!') if isinstance(
self.session, ba.DualTeamSession) else (
self.session, bs.DualTeamSession) else (
'Kill walkers for points! Dead player walker: 2 points!')
def get_instance_description_short(self) -> str | Sequence:
return ('Kill walkers for points! ',
'Dead player walker: 2 points!') if isinstance(
self.session, ba.DualTeamSession) else (
self.session, bs.DualTeamSession) else (
'Kill walkers for points! Dead player walker: 2 points!')
def on_player_join(self, player: Player) -> None:
if self.has_begun():
player.lives = 0
player.icons = []
ba.screenmessage(
ba.Lstr(resource='playerDelayedJoinText',
bs.broadcastmessage(
babase.Lstr(resource='playerDelayedJoinText',
subs=[('${PLAYER}', player.getname(full=True))]),
color=(0, 1, 0),
)
@ -314,13 +317,13 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
def on_begin(self) -> None:
super().on_begin()
self._start_time = ba.time()
self._start_time = bs.time()
self.setup_standard_time_limit(self._time_limit)
self.setup_standard_powerup_drops()
self.zombieQ = 1
if self._solo_mode:
self._vs_text = ba.NodeActor(
ba.newnode('text',
self._vs_text = bs.NodeActor(
bs.newnode('text',
attrs={
'position': (0, 105),
'h_attach': 'center',
@ -331,12 +334,12 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
'scale': 0.6,
'v_attach': 'bottom',
'color': (0.8, 0.8, 0.3, 1.0),
'text': ba.Lstr(resource='vsText')
'text': babase.Lstr(resource='vsText')
}))
# If balance-team-lives is on, add lives to the smaller team until
# total lives match.
if (isinstance(self.session, ba.DualTeamSession)
if (isinstance(self.session, bs.DualTeamSession)
and self._balance_total_lives and self.teams[0].players
and self.teams[1].players):
if self._get_total_team_lives(
@ -365,13 +368,13 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
# We could check game-over conditions at explicit trigger points,
# but lets just do the simple thing and poll it.
ba.timer(1.0, self._update, repeat=True)
bs.timer(1.0, self._update, repeat=True)
def _update_icons(self) -> None:
# pylint: disable=too-many-branches
# In free-for-all mode, everyone is just lined up along the bottom.
if isinstance(self.session, ba.FreeForAllSession):
if isinstance(self.session, bs.FreeForAllSession):
count = len(self.teams)
x_offs = 85
xval = x_offs * (count - 1) * -0.5
@ -437,7 +440,7 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
icon.update_for_lives()
xval += x_offs
def _get_spawn_point(self, player: Player) -> ba.Vec3 | None:
def _get_spawn_point(self, player: Player) -> babase.Vec3 | None:
del player # Unused.
# In solo-mode, if there's an existing live player on the map, spawn at
@ -455,10 +458,10 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
break
if living_player:
assert living_player_pos is not None
player_pos = ba.Vec3(living_player_pos)
points: list[tuple[float, ba.Vec3]] = []
player_pos = babase.Vec3(living_player_pos)
points: list[tuple[float, babase.Vec3]] = []
for team in self.teams:
start_pos = ba.Vec3(self.map.get_start_position(team.id))
start_pos = babase.Vec3(self.map.get_start_position(team.id))
points.append(
((start_pos - player_pos).length(), start_pos))
# Hmm.. we need to sorting vectors too?
@ -466,13 +469,13 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
return points[-1][1]
return None
def spawn_player(self, player: Player) -> ba.Actor:
def spawn_player(self, player: Player) -> bs.Actor:
position = self.map.get_ffa_start_position(self.players)
angle = 20
name = player.getname()
light_color = _math.normalized_color(player.color)
display_color = _ba.safecolor(player.color, target_intensity=0.75)
display_color = _babase.safecolor(player.color, target_intensity=0.75)
spaz = PlayerSpaz_Zom(color=player.color,
highlight=player.highlight,
character=player.character,
@ -500,14 +503,14 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
StandMessage(
position,
angle if angle is not None else random.uniform(0, 360)))
_ba.playsound(self._spawn_sound, 1, position=spaz.node.position)
light = _ba.newnode('light', attrs={'color': light_color})
bs.Sound.play(self._spawn_sound, 1, position=spaz.node.position)
light = bs.newnode('light', attrs={'color': light_color})
spaz.node.connectattr('position', light, 'position')
ba.animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0})
_ba.timer(0.5, light.delete)
bs.animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0})
bs.timer(0.5, light.delete)
if not self._solo_mode:
ba.timer(0.3, ba.Call(self._print_lives, player))
bs.timer(0.3, babase.Call(self._print_lives, player))
for icon in player.icons:
icon.handle_player_spawned()
@ -539,30 +542,30 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
respawn_time = round(max(1.0, respawn_time), 0)
if player.actor and not self.has_ended():
from bastd.actor.respawnicon import RespawnIcon
player.customdata['respawn_timer'] = _ba.Timer(
respawn_time, ba.WeakCall(
from bascenev1lib.actor.respawnicon import RespawnIcon
player.customdata['respawn_timer'] = bs.Timer(
respawn_time, bs.WeakCall(
self.spawn_player_if_exists_as_zombie, player))
player.customdata['respawn_icon'] = RespawnIcon(
player, respawn_time)
def spawn_player_if_exists_as_zombie(self, player: PlayerType) -> None:
def spawn_player_if_exists_as_zombie(self, player: PlayerT) -> None:
"""
A utility method which calls self.spawn_player() *only* if the
ba.Player provided still exists; handy for use in timers and whatnot.
bs.Player provided still exists; handy for use in timers and whatnot.
There is no need to override this; just override spawn_player().
"""
if player:
self.spawn_player_zombie(player)
def spawn_player_zombie(self, player: PlayerType) -> ba.Actor:
def spawn_player_zombie(self, player: PlayerT) -> bs.Actor:
position = self.map.get_ffa_start_position(self.players)
angle = 20
name = player.getname()
light_color = _math.normalized_color(player.color)
display_color = _ba.safecolor(player.color, target_intensity=0.75)
display_color = _babase.safecolor(player.color, target_intensity=0.75)
spaz = PlayerSpaz_Zom(color=player.color,
highlight=player.highlight,
character='Kronk2',
@ -591,21 +594,21 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
StandMessage(
position,
angle if angle is not None else random.uniform(0, 360)))
_ba.playsound(self._spawn_sound, 1, position=spaz.node.position)
light = _ba.newnode('light', attrs={'color': light_color})
bs.Sound.play(self._spawn_sound, 1, position=spaz.node.position)
light = bs.newnode('light', attrs={'color': light_color})
spaz.node.connectattr('position', light, 'position')
ba.animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0})
_ba.timer(0.5, light.delete)
bs.animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0})
bs.timer(0.5, light.delete)
if not self._solo_mode:
ba.timer(0.3, ba.Call(self._print_lives, player))
bs.timer(0.3, babase.Call(self._print_lives, player))
for icon in player.icons:
icon.handle_player_spawned()
return spaz
def _print_lives(self, player: Player) -> None:
from bastd.actor import popuptext
from bascenev1lib.actor import popuptext
# We get called in a timer so it's possible our player has left/etc.
if not player or not player.is_alive() or not player.node:
@ -642,13 +645,13 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
# Update icons in a moment since our team will be gone from the
# list then.
ba.timer(0, self._update_icons)
bs.timer(0, self._update_icons)
def _get_total_team_lives(self, team: Team) -> int:
return sum(player.lives for player in team.players)
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.PlayerDiedMessage):
# Augment standard behavior.
super().handlemessage(msg)
@ -665,7 +668,7 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
if msg._player in self.spazList:
self.spazList.remove(msg._player)
if player.lives < 0:
ba.print_error(
babase.print_error(
"Got lives < 0 in Elim; this shouldn't happen. solo:" +
str(self._solo_mode))
player.lives = 0
@ -677,7 +680,7 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
# Play big death sound on our last death
# or for every one in solo mode.
if self._solo_mode or player.lives == 0:
ba.playsound(SpazFactory.get().single_player_death_sound)
SpazFactory.get().single_player_death_sound.play()
# If we hit zero lives, we're dead (and our team might be too).
if player.lives == 0:
@ -732,16 +735,16 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
theScores) and theScores.count(max(theScores)) > 1:
pass
else:
self._round_end_timer = ba.Timer(0.5, self.end_game)
self._round_end_timer = bs.Timer(0.5, self.end_game)
else:
self._round_end_timer = ba.Timer(0.5, self.end_game)
self._round_end_timer = bs.Timer(0.5, self.end_game)
def spawn_zombie(self) -> None:
# We need a Z height...
thePt = list(self.get_random_point_in_play())
thePt2 = self.map.get_ffa_start_position(self.players)
thePt[1] = thePt2[1]
ba.timer(0.1, ba.Call(
bs.timer(0.1, babase.Call(
self._bots.spawn_bot, BrawlerBot, pos=thePt, spawn_time=1.0))
def _onSpazBotDied(self, DeathMsg) -> None:
@ -816,25 +819,25 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]):
setattr(BrawlerBot, 'color', (0.6, 0.6, 0.6))
setattr(BrawlerBot, 'highlight', (0.6, 0.6, 0.6))
setattr(BrawlerBot, 'character', 'Kronk')
results = ba.GameResults()
results = bs.GameResults()
self._vs_text = None # Kill our 'vs' if its there.
for team in self.teams:
results.set_team_score(team, team.score)
self.end(results=results)
# ba_meta export game
# ba_meta export bascenev1.GameActivity
class ZombieHordeCoop(ZombieHorde):
name = 'Zombie Horde'
@classmethod
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
return ['Football Stadium']
@classmethod
def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool:
return (issubclass(sessiontype, ba.CoopSession))
def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
return (issubclass(sessiontype, bs.CoopSession))
def _update(self) -> None:
if self.zombieQ > 0:
@ -855,12 +858,12 @@ class ZombieHordeCoop(ZombieHorde):
break
if not any(player.is_alive() for player in self.teams[0].players):
self._round_end_timer = ba.Timer(0.5, self.end_game)
self._round_end_timer = bs.Timer(0.5, self.end_game)
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
if isinstance(msg, bs.PlayerDiedMessage):
# Augment standard behavior.
ba.TeamGameActivity.handlemessage(self, msg)
bs.TeamGameActivity.handlemessage(self, msg)
player: Player = msg.getplayer(Player)
# If we have any icons, update their state.
for icon in player.icons:
@ -870,10 +873,10 @@ class ZombieHordeCoop(ZombieHorde):
# ba_meta export plugin
class ZombieHordeLevel(ba.Plugin):
class ZombieHordeLevel(babase.Plugin):
def on_app_running(self) -> None:
ba.app.add_coop_practice_level(
ba.Level(
babase.app.classic.add_coop_practice_level(
bs._level.Level(
'Zombie Horde',
gametype=ZombieHordeCoop,
settings={},

View file

@ -27,7 +27,7 @@ import _babase
import bascenev1 as bs
import bascenev1lib
import bauiv1 as bui
from baenv import TARGET_BALLISTICA_BUILD
from baenv import TARGET_BALLISTICA_BUILD as build_number
from typing import TYPE_CHECKING
@ -37,8 +37,8 @@ if TYPE_CHECKING:
ANDROID = babase.app.classic.platform == "android"
DIRPATH = Path(
f"{_babase.app.python_directory_user if TARGET_BALLISTICA_BUILD < 21282 else _babase.app.env.python_directory_user}/image_id.json")
APP_VERSION = _babase.app.version if TARGET_BALLISTICA_BUILD < 21282 else _babase.app.env.version
f"{_babase.app.python_directory_user if build_number < 21282 else _babase.app.env.python_directory_user}/image_id.json")
APP_VERSION = _babase.app.version if build_number < 21282 else _babase.app.env.version
if ANDROID: # !can add ios in future

View file

@ -98,7 +98,7 @@ class RagdollBGone(babase.Plugin):
# Pick a random death noise
sound = death_sounds[random.randrange(len(death_sounds))]
# Play the sound where our Spaz is
sound.play(position=args[0].node.position)
bs.Sound.play(sound, position=args[0].node.position)
# Delete our Spaz node immediately.
# Removing stuff is weird and prone to errors, so we're gonna delay it.
bs.timer(0.001, args[0].node.delete)