2024-02-01 11:57:50 +03:00
|
|
|
# Ported to api 8 by brostos using baport.(https://github.com/bombsquad-community/baport)
|
|
|
|
|
"""For 1.7.33"""
|
|
|
|
|
|
|
|
|
|
# ba_meta require api 8
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
|
|
|
|
|
|
import babase
|
|
|
|
|
import bauiv1 as bui
|
|
|
|
|
import bascenev1 as bs
|
|
|
|
|
import random
|
|
|
|
|
from bascenev1lib.actor.bomb import BombFactory, Blast, ImpactMessage
|
|
|
|
|
from bascenev1lib.actor.onscreentimer import OnScreenTimer
|
|
|
|
|
from bascenev1lib.gameutils import SharedObjects
|
|
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
|
from typing import Any, Sequence, Optional, Type
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Meteor(bs.Actor):
|
|
|
|
|
"""A giant meteor instead of bombs."""
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def __init__(self,
|
|
|
|
|
pos: Sequence[float] = (0.0, 1.0, 0.0),
|
|
|
|
|
velocity: Sequence[float] = (0.0, 0.0, 0.0)):
|
|
|
|
|
super().__init__()
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
shared = SharedObjects.get()
|
|
|
|
|
factory = BombFactory.get()
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
materials = (shared.object_material,
|
|
|
|
|
factory.impact_blast_material)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
self.pos = (pos[0], pos[1], pos[2])
|
|
|
|
|
self.velocity = (velocity[0], velocity[1], velocity[2])
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
self.node = bs.newnode(
|
|
|
|
|
'prop',
|
|
|
|
|
delegate=self,
|
|
|
|
|
attrs={
|
|
|
|
|
'position': self.pos,
|
|
|
|
|
'velocity': self.velocity,
|
|
|
|
|
'mesh': factory.sticky_bomb_mesh,
|
|
|
|
|
'color_texture': factory.tnt_tex,
|
|
|
|
|
'mesh_scale': 3.0,
|
|
|
|
|
'body_scale': 2.99,
|
|
|
|
|
'body': 'sphere',
|
|
|
|
|
'shadow_size': 0.5,
|
|
|
|
|
'reflection': 'soft',
|
|
|
|
|
'reflection_scale': [0.45],
|
|
|
|
|
'materials': materials
|
|
|
|
|
})
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def explode(self) -> None:
|
|
|
|
|
Blast(position=self.node.position,
|
|
|
|
|
velocity=self.node.velocity,
|
|
|
|
|
blast_type='tnt',
|
|
|
|
|
blast_radius=2.0)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def handlemessage(self, msg: Any) -> Any:
|
|
|
|
|
if isinstance(msg, bs.DieMessage):
|
|
|
|
|
if self.node:
|
|
|
|
|
self.node.delete()
|
|
|
|
|
elif isinstance(msg, ImpactMessage):
|
|
|
|
|
self.explode()
|
|
|
|
|
self.handlemessage(bs.DieMessage())
|
|
|
|
|
else:
|
|
|
|
|
super().handlemessage(msg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Player(bs.Player['Team']):
|
|
|
|
|
"""Our player type for this game."""
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def __init__(self):
|
|
|
|
|
super().__init__()
|
|
|
|
|
self.death_time: Optional[float] = None
|
|
|
|
|
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
class Team(bs.Team[Player]):
|
|
|
|
|
"""Our team type for this game."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ba_meta export bascenev1.GameActivity
|
|
|
|
|
class NewMeteorShowerGame(bs.TeamGameActivity[Player, Team]):
|
|
|
|
|
"""Minigame by Jetz."""
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
name = 'Extinction'
|
|
|
|
|
description = 'Survive the Extinction.'
|
|
|
|
|
available_settings = [
|
|
|
|
|
bs.BoolSetting('Epic Mode', default=False)]
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
announce_player_deaths = True
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
@classmethod
|
|
|
|
|
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
|
|
|
|
|
return ['Football Stadium']
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
@classmethod
|
|
|
|
|
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
|
|
|
|
|
return (issubclass(sessiontype, bs.FreeForAllSession)
|
|
|
|
|
or issubclass(sessiontype, bs.DualTeamSession))
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def __init__(self, settings: dict):
|
|
|
|
|
super().__init__(settings)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
self._epic_mode = bool(settings['Epic Mode'])
|
|
|
|
|
self._last_player_death_time: Optiobal[float] = None
|
|
|
|
|
self._meteor_time = 2.0
|
|
|
|
|
self._timer: Optional[OnScreenTimer] = None
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
self.default_music = (bs.MusicType.EPIC
|
|
|
|
|
if self._epic_mode else bs.MusicType.SURVIVAL)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
if self._epic_mode:
|
|
|
|
|
self.slow_motion = True
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def on_begin(self) -> None:
|
|
|
|
|
super().on_begin()
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
delay = 5.0 if len(self.players) > 2 else 2.5
|
|
|
|
|
if self._epic_mode:
|
|
|
|
|
delay *= 0.25
|
|
|
|
|
bs.timer(delay, self._decrement_meteor_time, repeat=True)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
delay = 3.0
|
|
|
|
|
if self._epic_mode:
|
|
|
|
|
delay *= 0.25
|
|
|
|
|
bs.timer(delay, self._set_meteor_timer)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
self._timer = OnScreenTimer()
|
|
|
|
|
self._timer.start()
|
|
|
|
|
self._check_end_game()
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def on_player_join(self, player: Player) -> None:
|
|
|
|
|
if self.has_begun():
|
|
|
|
|
bs.broadcastmessage(
|
|
|
|
|
babase.Lstr(resource='playerDelayedJoinText',
|
2024-02-01 08:58:54 +00:00
|
|
|
subs=[('${PLAYER}', player.getname(full=True))]),
|
2024-02-01 11:57:50 +03:00
|
|
|
color=(0, 1, 0),
|
|
|
|
|
)
|
|
|
|
|
assert self._timer is not None
|
|
|
|
|
player.death_time = self._timer.getstarttime()
|
|
|
|
|
return
|
|
|
|
|
self.spawn_player(player)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def spawn_player(self, player: Player) -> None:
|
|
|
|
|
spaz = self.spawn_player_spaz(player)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
spaz.connect_controls_to_player(enable_punch=False,
|
|
|
|
|
enable_pickup=False,
|
|
|
|
|
enable_bomb=False,
|
|
|
|
|
enable_jump=False)
|
|
|
|
|
spaz.play_big_death_sound = True
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
return spaz
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def on_player_leave(self, player: Player) -> None:
|
|
|
|
|
super().on_player_leave(player)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
self._check_end_game()
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def handlemessage(self, msg: Any) -> Any:
|
|
|
|
|
if isinstance(msg, bs.PlayerDiedMessage):
|
|
|
|
|
curtime = bs.time()
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
msg.getplayer(Player).death_time = curtime
|
|
|
|
|
bs.timer(1.0, self._check_end_game)
|
|
|
|
|
else:
|
|
|
|
|
return super().handlemessage(msg)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def _spawn_meteors(self) -> None:
|
|
|
|
|
pos = (random.randint(-6, 7), 12,
|
|
|
|
|
random.uniform(-2, 1))
|
|
|
|
|
velocity = (random.randint(-11, 11), 0,
|
|
|
|
|
random.uniform(-5, 5))
|
|
|
|
|
Meteor(pos=pos, velocity=velocity).autoretain()
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def _spawn_meteors_cluster(self) -> None:
|
|
|
|
|
delay = 0.0
|
|
|
|
|
for _i in range(random.randrange(1, 3)):
|
|
|
|
|
bs.timer(delay, self._spawn_meteors)
|
|
|
|
|
delay += 1
|
|
|
|
|
self._set_meteor_timer()
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def _decrement_meteor_time(self) -> None:
|
|
|
|
|
self._meteor_time = max(0.01, self._meteor_time * 0.9)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def _set_meteor_timer(self) -> None:
|
|
|
|
|
bs.timer((1.0 + 0.2 * random.random()) * self._meteor_time,
|
|
|
|
|
self._spawn_meteors_cluster)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def _check_end_game(self) -> None:
|
|
|
|
|
living_team_count = 0
|
|
|
|
|
for team in self.teams:
|
|
|
|
|
for player in team.players:
|
|
|
|
|
if player.is_alive():
|
|
|
|
|
living_team_count += 1
|
|
|
|
|
break
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
if isinstance(self.session, bs.CoopSession):
|
|
|
|
|
if living_team_count <= 0:
|
|
|
|
|
self.end_game()
|
|
|
|
|
else:
|
|
|
|
|
if living_team_count <= 1:
|
|
|
|
|
self.end_game()
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
def end_game(self) -> None:
|
|
|
|
|
cur_time = bs.time()
|
|
|
|
|
assert self._timer is not None
|
|
|
|
|
start_time = self._timer.getstarttime()
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
for team in self.teams:
|
|
|
|
|
for player in team.players:
|
|
|
|
|
survived = False
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
if player.death_time is None:
|
|
|
|
|
survived = True
|
|
|
|
|
player.death_time = cur_time + 1
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
score = int(player.death_time - self._timer.getstarttime())
|
|
|
|
|
if survived:
|
|
|
|
|
score += 50
|
|
|
|
|
self.stats.player_scored(player, score, screenmessage=False)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
self._timer.stop(endtime=self._last_player_death_time)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
results = bs.GameResults()
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
for team in self.teams:
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
longest_life = 0.0
|
|
|
|
|
for player in team.players:
|
|
|
|
|
assert player.death_time is not None
|
|
|
|
|
longest_life = max(longest_life,
|
|
|
|
|
player.death_time - start_time)
|
2024-02-01 08:58:54 +00:00
|
|
|
|
2024-02-01 11:57:50 +03:00
|
|
|
results.set_team_score(team, int(1000.0 * longest_life))
|
2024-02-01 08:58:54 +00:00
|
|
|
|
|
|
|
|
self.end(results=results)
|
2024-02-16 01:05:27 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
# ba_meta export plugin
|
|
|
|
|
class plugin(babase.Plugin):
|
|
|
|
|
def __init__(self):
|
|
|
|
|
## Campaign support ##
|
|
|
|
|
babase.app.classic.add_coop_practice_level(bs.Level(
|
2024-02-15 19:39:53 +00:00
|
|
|
name='Extinction',
|
2024-02-16 01:05:27 +05:30
|
|
|
gametype=NewMeteorShowerGame,
|
|
|
|
|
settings={'Epic Mode': False},
|
|
|
|
|
preview_texture_name='footballStadiumPreview'))
|
|
|
|
|
babase.app.classic.add_coop_practice_level(bs.Level('Epic Extinction',
|
2024-02-15 19:39:53 +00:00
|
|
|
gametype=NewMeteorShowerGame,
|
|
|
|
|
settings={'Epic Mode': True},
|
|
|
|
|
preview_texture_name='footballStadiumPreview'))
|