new mini games

This commit is contained in:
Ayush Saini 2023-06-05 01:32:24 +05:30
parent d8de5c4457
commit 25e60eaa8c
5 changed files with 1314 additions and 0 deletions

View file

@ -293,6 +293,62 @@
}
}
},
"demolition_war": {
"description": "BombFight on wooden floor flying in air.",
"external_url": "https://www.youtube.com/channel/UCaQajfKHrTPgiOhuias5iPg",
"authors": [
{
"name": "Mr.Smoothy",
"email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824"
}
],
"versions": {
"1.0.0": null
}
},
"castel_queen": {
"description": "Carry the queen for some duration in her room.",
"external_url": "https://www.youtube.com/channel/UCaQajfKHrTPgiOhuias5iPg",
"authors": [
{
"name": "Mr.Smoothy",
"email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824"
}
],
"versions": {
"1.0.0": null
}
},
"drone_war": {
"description": "Fly with Drone and attack with rocket launcher",
"external_url": "https://www.youtube.com/channel/UCaQajfKHrTPgiOhuias5iPg",
"authors": [
{
"name": "Mr.Smoothy",
"email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824"
}
],
"versions": {
"1.0.0": null
}
},
"the_spaz_game": {
"description": "Enemy Spaz Amoung us, kill correct person.",
"external_url": "https://www.youtube.com/channel/UCaQajfKHrTPgiOhuias5iPg",
"authors": [
{
"name": "Mr.Smoothy",
"email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824"
}
],
"versions": {
"1.0.0": null
}
},
"air_soccer": {
"description": "Play soccer while flying in air",
"external_url": "https://youtu.be/j6FFk7E6W_U",

View file

@ -0,0 +1,407 @@
# Released under the MIT License. See LICENSE for details.
#
"""
CastelQueen - Carry the Queen alone or with your team.
Author: Mr.Smoothy
Discord: https://discord.gg/ucyaesh
Youtube: https://www.youtube.com/c/HeySmoothy
Website: https://bombsquad-community.web.app
Github: https://github.com/bombsquad-community
"""
# ba_meta require api 7
# (see https://ballistica.net/wiki/meta-tag-system)
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
import _ba
from bastd.gameutils import SharedObjects
from bastd.actor.playerspaz import PlayerSpaz
from bastd.game.keepaway import KeepAwayGame, FlagState, Player
from bastd.actor import spaz
if TYPE_CHECKING:
from typing import Any, Sequence, Dict, Type, List, Optional, Union
# ba_meta export game
class ChooseQueen(KeepAwayGame):
name = 'FCUK The Queen'
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)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ['Creative Thoughts']
def get_instance_description(self) -> str | Sequence:
return 'FCUK the queen for ${ARG1} seconds.', self._hold_time
def get_instance_description_short(self) -> str | Sequence:
return 'FCUK the queen for ${ARG1} seconds', self._hold_time
def __init__(self, settings: dict):
super().__init__(settings)
shared = SharedObjects.get()
self.lifts = {}
self._room_wall_material = ba.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.add_actions(
conditions=('they_have_material', self._room_wall_material),
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)
))
self._queen_material.add_actions(
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)
))
self._room_wall_material.add_actions(
conditions=('they_have_material', self._queen_material),
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)
))
self._real_wall_material = ba.Material()
self._real_wall_material.add_actions(
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)
))
self._real_wall_material.add_actions(
conditions=('they_have_material', shared.player_material),
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)
))
def on_begin(self):
ba.getactivity().globalsnode.happy_thoughts_mode = True
super().on_begin()
self.make_map()
def _spawn_flag(self) -> None:
ba.playsound(self._swipsound)
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.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))
self._flag.hitpoints = 5000
self._flag.hitpoints_max = 5000
self._flag_state = FlagState.NEW
self._flag_light = ba.newnode(
'light',
owner=self._flag.node,
attrs={'intensity': 0.2, 'radius': 0.3, 'color': (0.2, 0.2, 0.2)},
)
assert self._flag.node
self._flag.node.connectattr('position', self._flag_light, 'position')
self._update_flag_state()
def _update_flag_state(self) -> None:
if not self._flag.node.exists():
self._spawn_flag()
for team in self.teams:
team.holdingflag = False
self._holding_players = []
for player in self.players:
holdingflag = False
try:
assert isinstance(player.actor, (PlayerSpaz, type(None)))
if (
player.actor
and player.actor.node
and player.actor.node.hold_node
):
holdingflag = (
player.actor.node.hold_node == self._flag.node
)
except Exception:
ba.print_exception('Error checking hold flag.')
if holdingflag:
self._holding_players.append(player)
player.team.holdingflag = True
holdingteams = set(t for t in self.teams if t.holdingflag)
prevstate = self._flag_state
assert self._flag is not None
assert self._flag_light
assert self._flag.node
if len(holdingteams) > 1:
self._flag_state = FlagState.CONTESTED
self._scoring_team = None
elif len(holdingteams) == 1:
holdingteam = list(holdingteams)[0]
self._flag_state = FlagState.HELD
self._scoring_team = holdingteam
else:
self._flag_state = FlagState.UNCONTESTED
self._scoring_team = None
if self._flag_state != prevstate:
ba.playsound(self._swipsound)
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
# Augment standard behavior.
super().handlemessage(msg)
self.respawn_player(msg.getplayer(Player))
elif isinstance(msg, (ba.PickedUpMessage, ba.DroppedMessage)):
self._update_flag_state()
else:
super().handlemessage(msg)
def make_map(self):
shared = SharedObjects.get()
_ba.get_foreground_host_activity()._map.leftwall.materials = [
shared.footing_material, self._real_wall_material]
_ba.get_foreground_host_activity()._map.rightwall.materials = [
shared.footing_material, self._real_wall_material]
_ba.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':
(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': (
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': (
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': (
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': (
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': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (15, 0.2, 2)})
self.create_static_step(0, 14.29)
# upper right
self.create_static_step(11, 16)
self.create_slope(8, 16, False)
self.create_static_step(3, 18)
# lower right
self.create_static_step(11, 12)
self.create_slope(6, 10, True)
self.create_static_step(3, 10)
# upper left
self.create_static_step(-11, 16)
self.create_slope(-8, 16, True)
self.create_static_step(-3, 18)
# lower left
self.create_static_step(-11, 12)
self.create_slope(-6, 10, False)
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':
(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':
(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),
'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.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),
'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]})
ba.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
y = y + 0.1
else:
x = x - 0.1
y = y + 0.1
class mapdefs:
points = {}
# noinspection PyDictCreation
boxes = {}
boxes['area_of_interest_bounds'] = (-1.045859963, 12.67722855,
-5.401537075) + (0.0, 0.0, 0.0) + (
42.46156851, 20.94044653, 0.6931564611)
points['ffa_spawn1'] = (-9.295167711, 8.010664315,
-5.44451005) + (1.555840357, 1.453808816, 0.1165648888)
points['ffa_spawn2'] = (7.484707127, 8.172681752, -5.614479365) + (
1.553861796, 1.453808816, 0.04419853907)
points['ffa_spawn3'] = (9.55724115, 11.30789446, -5.614479365) + (
1.337925849, 1.453808816, 0.04419853907)
points['ffa_spawn4'] = (-11.55747023, 10.99170684, -5.614479365) + (
1.337925849, 1.453808816, 0.04419853907)
points['ffa_spawn5'] = (-1.878892369, 9.46490571, -5.614479365) + (
1.337925849, 1.453808816, 0.04419853907)
points['ffa_spawn6'] = (-0.4912812943, 5.077006397, -5.521672101) + (
1.878332089, 1.453808816, 0.007578097856)
points['flag1'] = (-11.75152479, 8.057427485, -5.52)
points['flag2'] = (9.840909039, 8.188634282, -5.52)
points['flag3'] = (-0.2195258696, 5.010273907, -5.52)
points['flag4'] = (-0.04605809154, 12.73369108, -5.52)
points['flag_default'] = (-0.04201942896, 12.72374492, -5.52)
boxes['map_bounds'] = (-0.8748348681, 9.212941713, -5.729538885) + (
0.0, 0.0, 0.0) + (42.09666006, 26.19950145, 7.89541168)
points['powerup_spawn1'] = (1.160232442, 6.745963662, -5.469115985)
points['powerup_spawn2'] = (-1.899700206, 10.56447241, -5.505721177)
points['powerup_spawn3'] = (10.56098871, 12.25165669, -5.576232453)
points['powerup_spawn4'] = (-12.33530337, 12.25165669, -5.576232453)
points['spawn1'] = (-9.295167711, 8.010664315,
-5.44451005) + (1.555840357, 1.453808816, 0.1165648888)
points['spawn2'] = (7.484707127, 8.172681752,
-5.614479365) + (1.553861796, 1.453808816, 0.04419853907)
points['spawn_by_flag1'] = (-9.295167711, 8.010664315, -5.44451005) + (
1.555840357, 1.453808816, 0.1165648888)
points['spawn_by_flag2'] = (7.484707127, 8.172681752, -5.614479365) + (
1.553861796, 1.453808816, 0.04419853907)
points['spawn_by_flag3'] = (-1.45994593, 5.038762459, -5.535288724) + (
0.9516389866, 0.6666414677, 0.08607244075)
points['spawn_by_flag4'] = (0.4932087091, 12.74493212, -5.598987003) + (
0.5245740665, 0.5245740665, 0.01941146064)
class CreativeThoughts(ba.Map):
"""Freaking map by smoothy."""
defs = mapdefs
name = 'Creative Thoughts'
@classmethod
def get_play_types(cls) -> List[str]:
"""Return valid play types for this map."""
return [
'melee', 'keep_away', 'team_flag'
]
@classmethod
def get_preview_texture_name(cls) -> str:
return 'alwaysLandPreview'
@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')
}
return data
@classmethod
def get_music_type(cls) -> ba.MusicType:
return ba.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.add_actions(
conditions=(('they_are_younger_than', 9000), 'and',
('they_have_material', shared.player_material)),
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)
))
self._real_wall_material.add_actions(
conditions=('they_have_material', shared.player_material),
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)
))
self.background = ba.newnode(
'terrain',
attrs={
'model': self.preloaddata['bgmodel'],
'lighting': False,
'background': True,
'color_texture': ba.gettexture("rampageBGColor")
})
self.leftwall = ba.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': (
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': (
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': (
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': (
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': (
0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (35.4, 0.2, 2)})
gnode = ba.getactivity().globalsnode
gnode.happy_thoughts_mode = True
gnode.shadow_offset = (0.0, 8.0, 5.0)
gnode.tint = (1.3, 1.23, 1.0)
gnode.ambient_color = (1.3, 1.23, 1.0)
gnode.vignette_outer = (0.64, 0.59, 0.69)
gnode.vignette_inner = (0.95, 0.95, 0.93)
gnode.vr_near_clip = 1.0
self.is_flying = True
# throw out some tips on flying
txt = ba.newnode('text',
attrs={
'text': ba.Lstr(resource='pressJumpToFlyText'),
'scale': 1.2,
'maxwidth': 800,
'position': (0, 200),
'shadow': 0.5,
'flatness': 0.5,
'h_align': 'center',
'v_attach': 'bottom'
})
cmb = ba.newnode('combine',
owner=txt,
attrs={
'size': 4,
'input0': 0.3,
'input1': 0.9,
'input2': 0.0
})
ba.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)
try:
ba._map.register_map(CreativeThoughts)
except:
pass

View file

@ -0,0 +1,303 @@
# ba_meta require api 7
"""
DemolitionWar - BombFight on wooden floor flying in air.
Author: Mr.Smoothy
Discord: https://discord.gg/ucyaesh
Youtube: https://www.youtube.com/c/HeySmoothy
Website: https://bombsquad-community.web.app
Github: https://github.com/bombsquad-community
"""
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
from bastd.game.elimination import EliminationGame, Player
from bastd.gameutils import SharedObjects
from bastd.actor.bomb import BombFactory
import random
from bastd.actor.playerspaz import PlayerSpaz
if TYPE_CHECKING:
from typing import Any, Sequence
# ba_meta export game
class DemolitionWar(EliminationGame):
name = 'DemolitionWar'
description = 'Last remaining alive wins.'
scoreconfig = ba.ScoreConfig(
label='Survived', scoretype=ba.ScoreType.SECONDS, none_is_winner=True
)
# Show messages when players die since it's meaningful here.
announce_player_deaths = True
allow_mid_activity_joins = False
@classmethod
def get_available_settings(
cls, sessiontype: type[ba.Session]
) -> list[ba.Setting]:
settings = [
ba.IntSetting(
'Lives Per Player',
default=1,
min_value=1,
max_value=10,
increment=1,
),
ba.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
('1 Minute', 60),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600),
('20 Minutes', 1200),
],
default=0,
),
ba.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
('Short', 0.5),
('Normal', 1.0),
('Long', 2.0),
('Longer', 4.0),
],
default=1.0,
),
ba.BoolSetting('Epic Mode', default=False),
]
if issubclass(sessiontype, ba.DualTeamSession):
settings.append(ba.BoolSetting('Solo Mode', default=False))
settings.append(
ba.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
)
@classmethod
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
return ['Wooden Floor']
def __init__(self, settings: dict):
super().__init__(settings)
self._lives_per_player = 1
self._solo_mode = False
self._balance_total_lives = False
def spawn_player(self, player: Player) -> ba.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]
x = random.randrange(0, len(p))
y = random.randrange(0, len(q))
spaz = self.spawn_player_spaz(player, position=(p[x], 1.8, q[y]))
spaz.bomb_type = 'impact'
# Let's reconnect this player's controls to this
# spaz but *without* the ability to attack or pick stuff up.
spaz.connect_controls_to_player(enable_punch=False,
enable_bomb=True,
enable_pickup=True)
# Also lets have them make some noise when they die.
spaz.play_big_death_sound = True
return spaz
def on_begin(self) -> None:
super().on_begin()
self.map_extend()
def on_blast(self):
node = ba.getcollision().sourcenode
ba.emitfx((node.position[0], 0.9, node.position[2]),
(0, 2, 0), 30, 1, spread=1, chunk_type='splinter')
ba.timer(0.1, ba.Call(node.delete))
def map_extend(self):
# TODO need to improve here , so we can increase size of map easily with settings
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]
factory = BombFactory.get()
self.ramp_bomb = ba.Material()
self.ramp_bomb.add_actions(
conditions=('they_have_material', factory.bomb_material),
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True),
('call', 'at_connect', ba.Call(self.on_blast))
))
self.ramps = []
for i in p:
for j in q:
self.ramps.append(self.create_ramp(i, j))
def create_ramp(self, x, z):
shared = SharedObjects.get()
self._real_collied_material = ba.Material()
self._real_collied_material.add_actions(
actions=(
('modify_part_collision', 'collide', True),
('modify_part_collision', 'physical', True)
))
self.mat = ba.Material()
self.mat.add_actions(
actions=(('modify_part_collision', 'physical', False),
('modify_part_collision', 'collide', False))
)
pos = (x, 0, z)
ud_1_r = ba.newnode('region', attrs={'position': pos, 'scale': (1.5, 1, 1.5), 'type': 'box', 'materials': [
shared.footing_material, self._real_collied_material, self.ramp_bomb]})
node = ba.newnode('prop',
owner=ud_1_r,
attrs={
'model': ba.getmodel('image1x1'),
'light_model': ba.getmodel('powerupSimple'),
'position': (2, 7, 2),
'body': 'puck',
'shadow_size': 0.0,
'velocity': (0, 0, 0),
'color_texture': ba.gettexture('tnt'),
'model_scale': 1.5,
'reflection_scale': [1.5],
'materials': [self.mat, shared.object_material, shared.footing_material],
'density': 9000000000
})
node.changerotation(1, 0, 0)
mnode = ba.newnode('math',
owner=ud_1_r,
attrs={
'input1': (0, 0.6, 0),
'operation': 'add'
})
ud_1_r.connectattr('position', mnode, 'input2')
mnode.connectattr('output', node, 'position')
return ud_1_r
class mapdefs:
points = {}
# noinspection PyDictCreation
boxes = {}
boxes['area_of_interest_bounds'] = (0.0, 1.185751251, 0.4326226188) + (
0.0, 0.0, 0.0) + (29.8180273, 11.57249038, 18.89134176)
boxes['edge_box'] = (-0.103873591, 0.4133341891, 0.4294651013) + (
0.0, 0.0, 0.0) + (22.48295719, 1.290242794, 8.990252454)
points['ffa_spawn1'] = (-0.08015551329, 0.02275111462,
-4.373674593) + (8.895057015, 1.0, 0.444350722)
points['ffa_spawn2'] = (-0.08015551329, 0.02275111462,
4.076288941) + (8.895057015, 1.0, 0.444350722)
points['flag1'] = (-10.99027878, 0.05744967453, 0.1095578275)
points['flag2'] = (11.01486398, 0.03986567039, 0.1095578275)
points['flag_default'] = (-0.1001374046, 0.04180340146, 0.1095578275)
boxes['goal1'] = (12.22454533, 1.0,
0.1087926362) + (0.0, 0.0, 0.0) + (2.0, 2.0, 12.97466313)
boxes['goal2'] = (-12.15961605, 1.0,
0.1097860203) + (0.0, 0.0, 0.0) + (2.0, 2.0, 13.11856424)
boxes['map_bounds'] = (0.0, 1.185751251, 0.4326226188) + (0.0, 0.0, 0.0) + (
42.09506485, 22.81173179, 29.76723155)
points['powerup_spawn1'] = (5.414681236, 0.9515026107, -5.037912441)
points['powerup_spawn2'] = (-5.555402285, 0.9515026107, -5.037912441)
points['powerup_spawn3'] = (5.414681236, 0.9515026107, 5.148223181)
points['powerup_spawn4'] = (-5.737266365, 0.9515026107, 5.148223181)
points['spawn1'] = (-10.03866341, 0.02275111462, 0.0) + (0.5, 1.0, 4.0)
points['spawn2'] = (9.823107149, 0.01092306765, 0.0) + (0.5, 1.0, 4.0)
points['tnt1'] = (-0.08421587483, 0.9515026107, -0.7762602271)
class WoodenFloor(ba.Map):
"""Stadium map for football games."""
defs = mapdefs
defs.points['spawn1'] = (-12.03866341, 0.02275111462, 0.0) + (0.5, 1.0, 4.0)
defs.points['spawn2'] = (12.823107149, 0.01092306765, 0.0) + (0.5, 1.0, 4.0)
name = 'Wooden Floor'
@classmethod
def get_play_types(cls) -> list[str]:
"""Return valid play types for this map."""
return ['melee', 'football', 'team_flag', 'keep_away']
@classmethod
def get_preview_texture_name(cls) -> str:
return 'footballStadiumPreview'
@classmethod
def on_preload(cls) -> Any:
data: dict[str, Any] = {
'model_bg': ba.getmodel('doomShroomBG'),
'bg_vr_fill_model': ba.getmodel('natureBackgroundVRFill'),
'collide_model': ba.getcollidemodel('bridgitLevelCollide'),
'tex': ba.gettexture('bridgitLevelColor'),
'model_bg_tex': ba.gettexture('doomShroomBGColor'),
'collide_bg': ba.getcollidemodel('natureBackgroundCollide'),
'railing_collide_model':
(ba.getcollidemodel('bridgitLevelRailingCollide')),
'bg_material': ba.Material()
}
data['bg_material'].add_actions(actions=('modify_part_collision',
'friction', 10.0))
return data
def __init__(self) -> None:
super().__init__()
shared = SharedObjects.get()
self.background = ba.newnode(
'terrain',
attrs={
'model': self.preloaddata['model_bg'],
'lighting': False,
'background': True,
'color_texture': self.preloaddata['model_bg_tex']
})
self.vr = ba.newnode('terrain',
attrs={
'model': self.preloaddata['bg_vr_fill_model'],
'lighting': False,
'vr_only': True,
'background': True,
'color_texture': self.preloaddata['model_bg_tex']
})
gnode = ba.getactivity().globalsnode
gnode.tint = (1.3, 1.2, 1.0)
gnode.ambient_color = (1.3, 1.2, 1.0)
gnode.vignette_outer = (0.57, 0.57, 0.57)
gnode.vignette_inner = (0.9, 0.9, 0.9)
gnode.vr_camera_offset = (0, -0.8, -1.1)
gnode.vr_near_clip = 0.5
def is_point_near_edge(self,
point: ba.Vec3,
running: bool = False) -> bool:
box_position = self.defs.boxes['edge_box'][0:3]
box_scale = self.defs.boxes['edge_box'][6:9]
xpos = (point.x - box_position[0]) / box_scale[0]
zpos = (point.z - box_position[2]) / box_scale[2]
return xpos < -0.5 or xpos > 0.5 or zpos < -0.5 or zpos > 0.5
def _handle_player_collide(self):
try:
player = ba.getcollision().opposingnode.getdelegate(
PlayerSpaz, True)
except ba.NotFoundError:
return
if player.is_alive():
player.shatter(True)
try:
ba._map.register_map(WoodenFloor)
except:
pass

View file

@ -0,0 +1,426 @@
# Released under the MIT License. See LICENSE for details.
#
"""
DroneWar - Attack enemies with drone, Fly with drone and fire rocket launcher.
Author: Mr.Smoothy
Discord: https://discord.gg/ucyaesh
Youtube: https://www.youtube.com/c/HeySmoothy
Website: https://bombsquad-community.web.app
Github: https://github.com/bombsquad-community
"""
# ba_meta require api 7
# (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
from bastd.gameutils import SharedObjects
from bastd.actor.playerspaz import PlayerSpaz, PlayerType
from bastd.game.deathmatch import DeathMatchGame, Player
from bastd.actor import spaz
if TYPE_CHECKING:
from typing import Any, Sequence, Dict, Type, List, Optional, Union
STORAGE_ATTR_NAME = f'_shared_{__name__}_factory'
# SMoothy's Drone (fixed version of floater) with rocket launcher
# use drone as long as you want , unlike floater which dies after being idle.
class Drone(ba.Actor):
def __init__(self, spaz):
super().__init__()
shared = SharedObjects.get()
self._drone_material = ba.Material()
self.loop_ascend = None
self.loop_descend = None
self.loop_lr = None
self.loop_ud = None
self.rocket_launcher = None
self.x_direction = 0
self.z_direction = 0
self.spaz = spaz
self._drone_material.add_actions(
conditions=('they_have_material',
shared.player_material),
actions=(('modify_node_collision', 'collide', True),
('modify_part_collision', 'physical', True)))
self._drone_material.add_actions(
conditions=(('they_have_material',
shared.object_material), 'or',
('they_have_material',
shared.footing_material), 'or',
('they_have_material',
self._drone_material)),
actions=('modify_part_collision', 'physical', False))
self.node = ba.newnode(
'prop',
delegate=self,
owner = None,
attrs={
'position': spaz.node.position,
'model':ba.getmodel('landMine'),
'light_model':ba.getmodel('landMine'),
'body':'landMine',
'body_scale':1,
'model_scale':1,
'shadow_size':0.25,
'density':999999,
'gravity_scale':0.0,
'color_texture':ba.gettexture('achievementCrossHair'),
'reflection':'soft',
'reflection_scale': [0.25],
'materials':[shared.footing_material, self._drone_material]
})
self.grab_node = ba.newnode(
'prop',
owner=self.node,
attrs={
'position': (0, 0, 0),
'body':'sphere',
'model': None,
'color_texture':None,
'body_scale':0.2,
'reflection':'powerup',
'density':999999,
'reflection_scale': [1.0],
'model_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',
owner=self.node,
attrs={
'input0':self.spaz.node.position[0],
'input1':self.spaz.node.position[1]+3,
'input2':self.spaz.node.position[2],
'size':3
})
self._rcombine.connectattr('output',self.node,'position')
def set_rocket_launcher(self, launcher: RocketLauncher):
self.rocket_launcher = launcher
def fire(self):
if hasattr(self.grab_node,"position"):
self.rocket_launcher.shot(self.spaz, self.x_direction, self.z_direction , (self.grab_node.position[0], self.grab_node.position[1] -1, self.grab_node.position[2]))
def ascend(self):
def loop():
if self.node.exists():
ba.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)
def pause_movement(self):
self.loop_ascend = None
def decend(self):
def loop():
if self.node.exists():
ba.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 )
def pause_lr(self):
self.loop_lr = None
def pause_ud(self):
self.loop_ud = None
def left_(self, value = -1):
def loop():
if self.node.exists():
ba.animate( self._rcombine,'input0',{
0:self.node.position[0],
1:self.node.position[0] + 2 * value
})
if value == 0.0:
self.loop_lr = None
else:
self.x_direction = value
self.z_direction = 0
loop()
self.loop_lr = ba.Timer(1, loop , repeat = True )
def right_(self, value = 1):
def loop():
if self.node.exists():
ba.animate( self._rcombine,'input0',{
0:self.node.position[0],
1:self.node.position[0] + 2 * value
})
if value == 0.0:
self.loop_lr = None
else:
self.x_direction = value
self.z_direction = 0
loop()
self.loop_lr = ba.Timer(1, loop , repeat = True )
def up_(self, value=1):
def loop():
if self.node.exists():
ba.animate( self._rcombine,'input2',{
0:self.node.position[2],
1:self.node.position[2] - 2 * value
})
if value == 0.0:
self.loop_ud = None
else:
self.x_direction = 0
self.z_direction = - value
loop()
self.loop_ud = ba.Timer(1, loop , repeat = True )
def down_(self, value=-1):
def loop():
if self.node.exists():
ba.animate( self._rcombine,'input2',{
0:self.node.position[2],
1:self.node.position[2] - 2 * value
})
if value == 0.0:
self.loop_ud = None
else:
self.x_direction = 0
self.z_direction = - value
loop()
self.loop_ud = ba.Timer(1, loop , repeat = True )
def handlemessage(self, msg):
if isinstance(msg, ba.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())
else:
super().handlemessage(msg)
# =============================================Copied from Quake Game - Dliwk =====================================================================
class RocketFactory:
"""Quake Rocket factory"""
def __init__(self) -> None:
self.ball_material = ba.Material()
self.ball_material.add_actions(
conditions=((('we_are_younger_than', 5), 'or',
('they_are_younger_than', 5)), 'and',
('they_have_material',
SharedObjects.get().object_material)),
actions=('modify_node_collision', 'collide', False))
self.ball_material.add_actions(
conditions=('they_have_material',
SharedObjects.get().pickup_material),
actions=('modify_part_collision', 'use_node_collide', False))
self.ball_material.add_actions(actions=('modify_part_collision',
'friction', 0))
self.ball_material.add_actions(
conditions=(('they_have_material',
SharedObjects.get().footing_material), 'or',
('they_have_material',
SharedObjects.get().object_material)),
actions=('message', 'our_node', 'at_connect', ImpactMessage()))
@classmethod
def get(cls):
"""Get factory if exists else create new"""
activity = ba.getactivity()
if hasattr(activity, STORAGE_ATTR_NAME):
return getattr(activity, STORAGE_ATTR_NAME)
factory = cls()
setattr(activity, STORAGE_ATTR_NAME, factory)
return factory
class RocketLauncher:
"""Very dangerous weapon"""
def __init__(self):
self.last_shot = ba.time()
def give(self, spaz: spaz.Spaz) -> None:
"""Give spaz a rocket launcher"""
spaz.punch_callback = self.shot
self.last_shot = ba.time()
# FIXME
# noinspection PyUnresolvedReferences
def shot(self, spaz, x, z, position) -> None:
"""Release a rocket"""
time = ba.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()
vel = [v * mag for v in direction]
Rocket(position=position,
velocity=vel,
owner=spaz.getplayer(ba.Player),
source_player=spaz.getplayer(ba.Player),
color=spaz.node.color).autoretain()
class ImpactMessage:
"""Rocket touched something"""
class Rocket(ba.Actor):
"""Epic rocket from rocket launcher"""
def __init__(self,
position=(0, 5, 0),
velocity=(1, 0, 0),
source_player=None,
owner=None,
color=(1.0, 0.2, 0.2)) -> None:
super().__init__()
self.source_player = source_player
self.owner = owner
self._color = color
factory = RocketFactory.get()
self.node = ba.newnode('prop',
delegate=self,
attrs={
'position': position,
'velocity': velocity,
'model': ba.getmodel('impactBomb'),
'body': 'sphere',
'color_texture': ba.gettexture(
'bunnyColor'),
'model_scale': 0.2,
'is_area_of_interest': True,
'body_scale': 0.8,
'materials': [
SharedObjects.get().object_material,
factory.ball_material]
}) # yapf: disable
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._emit_timer = ba.Timer(0.001, ba.WeakCall(self.emit), repeat=True)
self.base_pos_y = self.node.position[1]
ba.camerashake(5.0)
def emit(self) -> None:
"""Emit a trace after rocket"""
ba.emitfx(position=self.node.position,
scale=0.4,
spread=0.01,
chunk_type='spark')
if not self.node:
return
self.node.position = (self.node.position[0], self.base_pos_y,
self.node.position[2]) # ignore y
ba.newnode('explosion',
owner=self.node,
attrs={
'position': self.node.position,
'radius': 0.2,
'color': self._color
})
def handlemessage(self, msg: Any) -> Any:
"""Message handling for rocket"""
super().handlemessage(msg)
if isinstance(msg, ImpactMessage):
self.node.handlemessage(ba.DieMessage())
elif isinstance(msg, ba.DieMessage):
if self.node:
Blast(position=self.node.position,
blast_radius=2,
source_player=self.source_player)
self.node.delete()
self._emit_timer = None
elif isinstance(msg, ba.OutOfBoundsMessage):
self.handlemessage(ba.DieMessage())
# ba_meta export game
class ChooseQueen(DeathMatchGame):
name = 'Drone War'
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return issubclass(sessiontype, ba.DualTeamSession)
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ['Football Stadium']
def spawn_player_spaz(
self,
player: PlayerType,
position: Sequence[float] | None = None,
angle: float | None = None,
) -> PlayerSpaz:
spaz = super().spawn_player_spaz(player, position, angle)
self.spawn_drone(spaz)
return spaz
def on_begin(self):
super().on_begin()
shared = SharedObjects.get()
self.ground_material = ba.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 )),
),
)
pos=(0,0.1,-5)
self.main_region=ba.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(
PlayerSpaz, True)
except ba.NotFoundError:
return
if player.is_alive():
player.shatter(True)
def spawn_drone(self, spaz):
with ba.Context(_ba.get_foreground_host_activity()):
drone = Drone(spaz)
r_launcher = RocketLauncher()
drone.set_rocket_launcher(r_launcher)
player = spaz.getplayer(Player, True)
spaz.node.hold_node = drone.grab_node
player.actor.disconnect_controls_from_player()
player.resetinput()
player.assigninput(InputType.PICK_UP_PRESS, drone.ascend)
player.assigninput(InputType.PICK_UP_RELEASE, drone.pause_movement)
player.assigninput(InputType.JUMP_PRESS, drone.decend)
player.assigninput(InputType.PUNCH_PRESS, drone.fire)
player.assigninput(InputType.LEFT_PRESS, drone.left_)
player.assigninput(InputType.RIGHT_PRESS, drone.right_)
player.assigninput(InputType.LEFT_RELEASE, drone.pause_lr)
player.assigninput(InputType.RIGHT_RELEASE, drone.pause_lr)
player.assigninput(InputType.UP_PRESS, drone.up_)
player.assigninput(InputType.DOWN_PRESS, drone.down_)
player.assigninput(InputType.UP_RELEASE, drone.pause_ud)
player.assigninput(InputType.DOWN_RELEASE, drone.pause_ud)

View file

@ -0,0 +1,122 @@
# ba_meta require api 7
"""
TheSpazGame - Mini game where all characters looks identical , identify enemies and kill them.
Author: Mr.Smoothy
Discord: https://discord.gg/ucyaesh
Youtube: https://www.youtube.com/c/HeySmoothy
Website: https://bombsquad-community.web.app
Github: https://github.com/bombsquad-community
"""
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 random
if TYPE_CHECKING:
from typing import Any, Sequence
CHARACTER = 'Spaz'
# ba_meta export game
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
)
announce_player_deaths = False
allow_mid_activity_joins = False
@classmethod
def get_available_settings(
cls, sessiontype: type[ba.Session]
) -> list[ba.Setting]:
settings = [
ba.IntSetting(
'Lives Per Player',
default=1,
min_value=1,
max_value=10,
increment=1,
),
ba.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
('1 Minute', 60),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600),
('20 Minutes', 1200),
],
default=0,
),
ba.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.15)
],
default=1.0,
),
ba.BoolSetting('Epic Mode', default=False),
]
if issubclass(sessiontype, ba.DualTeamSession):
settings.append(ba.BoolSetting('Solo Mode', default=False))
settings.append(
ba.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
)
@classmethod
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
return ba.getmaps('melee')
def get_instance_description(self) -> str | Sequence:
return (
'Enemy Spaz AmongUs. Kill them all'
)
def get_instance_description_short(self) -> str | Sequence:
return (
'Enemy Spaz AmongUs. Kill them all'
)
def __init__(self, settings: dict):
super().__init__(settings)
self._solo_mode = False
def spawn_player(self, player: Player) -> ba.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]
x = random.randrange(0, len(p))
y = random.randrange(0, len(q))
spaz = self.spawn_player_spaz(player, position=(p[x], 1.8, q[y]))
spaz.node.color = (1,1,1)
spaz.node.highlight = (1,0.4,1)
self.update_appearance(spaz, character=CHARACTER)
# Also lets have them make some noise when they die.
spaz.play_big_death_sound = True
return spaz
def update_appearance(self, spaz, character):
factory = SpazFactory.get()
media = factory.get_media(character)
for field, value in media.items():
setattr(spaz.node, field, value)
spaz.node.style = factory.get_style(character)
spaz.node.name = ''