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

@ -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],