mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-26 17:03:14 +08:00
Fixed a bug with player positions being incorrect
This commit is contained in:
parent
90b028da18
commit
d6ccf2b12d
@ -367,13 +367,8 @@ class Map(Actor):
|
||||
# Get positions for existing players.
|
||||
player_pts = []
|
||||
for player in players:
|
||||
try:
|
||||
if player and player.node:
|
||||
pnt = _ba.Vec3(player.node.position)
|
||||
player_pts.append(pnt)
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception()
|
||||
if player.is_alive():
|
||||
player_pts.append(player.position)
|
||||
|
||||
def _getpt() -> Sequence[float]:
|
||||
point = self.ffa_spawn_points[self._next_ffa_start_index]
|
||||
|
||||
@ -24,6 +24,8 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, TypeVar, Generic
|
||||
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import (Type, Optional, Sequence, Dict, Any, Union, Tuple,
|
||||
Callable)
|
||||
@ -66,7 +68,6 @@ class Player(Generic[TeamType]):
|
||||
(internal)
|
||||
"""
|
||||
from ba._nodeactor import NodeActor
|
||||
import _ba
|
||||
|
||||
# Sanity check; if a dataclass is created that inherits from us,
|
||||
# it will define an equality operator by default which will break
|
||||
@ -92,6 +93,8 @@ class Player(Generic[TeamType]):
|
||||
self.gamedata = sessionplayer.gamedata
|
||||
|
||||
# Create our player node in the current activity.
|
||||
# Note: do we want to save a few cycles here by managing our player
|
||||
# node manually instead of wrapping it in a NodeActor?
|
||||
node = _ba.newnode('player', attrs={'playerID': sessionplayer.id})
|
||||
self._nodeactor = NodeActor(node)
|
||||
sessionplayer.set_node(node)
|
||||
@ -118,6 +121,15 @@ class Player(Generic[TeamType]):
|
||||
raise _error.NodeNotFoundError
|
||||
return self._nodeactor.node
|
||||
|
||||
@property
|
||||
def position(self) -> ba.Vec3:
|
||||
"""The position of the player, as defined by its current Actor.
|
||||
|
||||
This value should not be used when the player has no Actor, as
|
||||
it is undefined in that case.
|
||||
"""
|
||||
return _ba.Vec3(self.node.position)
|
||||
|
||||
def exists(self) -> bool:
|
||||
"""Whether the underlying player still exists.
|
||||
|
||||
|
||||
@ -87,14 +87,7 @@ class PlayerSpaz(Spaz, Generic[PlayerType]):
|
||||
self.held_count = 0
|
||||
self.last_player_held_by: Optional[PlayerType] = None
|
||||
self._player = player
|
||||
self.playertype = type(player)
|
||||
|
||||
# Grab the node for this player and wire it to follow our spaz
|
||||
# (so players' controllers know where to draw their guides, etc).
|
||||
if player:
|
||||
assert self.node
|
||||
assert player.node
|
||||
self.node.connectattr('torso_position', player.node, 'position')
|
||||
self._drive_player_position()
|
||||
|
||||
@property
|
||||
def player(self) -> PlayerType:
|
||||
@ -200,7 +193,7 @@ class PlayerSpaz(Spaz, Generic[PlayerType]):
|
||||
if isinstance(msg, ba.PickedUpMessage):
|
||||
super().handlemessage(msg) # Augment standard behavior.
|
||||
self.held_count += 1
|
||||
picked_up_by = ba.playercast_o(self.playertype,
|
||||
picked_up_by = ba.playercast_o(type(self._player),
|
||||
msg.node.source_player)
|
||||
if picked_up_by:
|
||||
self.last_player_held_by = picked_up_by
|
||||
@ -212,7 +205,7 @@ class PlayerSpaz(Spaz, Generic[PlayerType]):
|
||||
|
||||
# Let's count someone dropping us as an attack.
|
||||
try:
|
||||
picked_up_by_2 = ba.playercast_o(self.playertype,
|
||||
picked_up_by_2 = ba.playercast_o(type(self._player),
|
||||
msg.node.source_player)
|
||||
except Exception:
|
||||
picked_up_by_2 = None
|
||||
@ -220,6 +213,14 @@ class PlayerSpaz(Spaz, Generic[PlayerType]):
|
||||
self.last_player_attacked_by = picked_up_by_2
|
||||
self.last_attacked_time = ba.time()
|
||||
self.last_attacked_type = ('picked_up', 'default')
|
||||
elif isinstance(msg, ba.StandMessage):
|
||||
super().handlemessage(msg) # Augment standard behavior.
|
||||
|
||||
# Our Spaz was just moved somewhere. Explicitly update
|
||||
# our associated player's position in case it is being used
|
||||
# for logic (otherwise it will be out of date until next step)
|
||||
self._drive_player_position()
|
||||
|
||||
elif isinstance(msg, ba.DieMessage):
|
||||
|
||||
# Report player deaths to the game.
|
||||
@ -271,7 +272,7 @@ class PlayerSpaz(Spaz, Generic[PlayerType]):
|
||||
|
||||
# Keep track of the player who last hit us for point rewarding.
|
||||
elif isinstance(msg, ba.HitMessage):
|
||||
source_player = msg.get_source_player(self.playertype)
|
||||
source_player = msg.get_source_player(type(self._player))
|
||||
if source_player:
|
||||
self.last_player_attacked_by = source_player
|
||||
self.last_attacked_time = ba.time()
|
||||
@ -282,3 +283,16 @@ class PlayerSpaz(Spaz, Generic[PlayerType]):
|
||||
activity.handlemessage(PlayerSpazHurtMessage(self))
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
|
||||
def _drive_player_position(self) -> None:
|
||||
"""Drive our ba.Player's official position
|
||||
|
||||
If our position is changed explicitly, this should be called again
|
||||
to instantly update the player position (otherwise it would be out
|
||||
of date until the next sim step)
|
||||
"""
|
||||
player = self._player
|
||||
if player:
|
||||
assert self.node
|
||||
assert player.node
|
||||
self.node.connectattr('torso_position', player.node, 'position')
|
||||
|
||||
@ -1070,9 +1070,9 @@ class Spaz(ba.Actor):
|
||||
if self.hitpoints > 0:
|
||||
|
||||
# It's kinda crappy to die from impacts, so lets reduce
|
||||
# impact damage by a reasonable amount if it'll keep us alive
|
||||
# impact damage by a reasonable amount *if* it'll keep us alive
|
||||
if msg.hit_type == 'impact' and damage > self.hitpoints:
|
||||
# drop damage to whatever puts us at 10 hit points,
|
||||
# Drop damage to whatever puts us at 10 hit points,
|
||||
# or 200 less than it used to be whichever is greater
|
||||
# (so it *can* still kill us if its high enough)
|
||||
newdamage = max(damage - 200, self.hitpoints - 10)
|
||||
@ -1081,27 +1081,28 @@ class Spaz(ba.Actor):
|
||||
|
||||
# If we're holding something, drop it.
|
||||
if damage > 0.0 and self.node.hold_node:
|
||||
# self.node.hold_node = ba.Node(None)
|
||||
self.node.hold_node = None
|
||||
self.hitpoints -= damage
|
||||
self.node.hurt = 1.0 - float(
|
||||
self.hitpoints) / self.hitpoints_max
|
||||
|
||||
# If we're cursed, *any* damage blows us up.
|
||||
if self._cursed and damage > 0:
|
||||
ba.timer(
|
||||
0.05,
|
||||
ba.WeakCall(self.curse_explode,
|
||||
msg.get_source_player(ba.Player)))
|
||||
# if we're frozen, shatter.. otherwise die if we hit zero
|
||||
|
||||
# If we're frozen, shatter.. otherwise die if we hit zero
|
||||
if self.frozen and (damage > 200 or self.hitpoints <= 0):
|
||||
self.shatter()
|
||||
elif self.hitpoints <= 0:
|
||||
self.node.handlemessage(
|
||||
ba.DieMessage(how=ba.DeathType.IMPACT))
|
||||
|
||||
# if we're dead, take a look at the smoothed damage val
|
||||
# If we're dead, take a look at the smoothed damage value
|
||||
# (which gives us a smoothed average of recent damage) and shatter
|
||||
# us if its grown high enough
|
||||
# us if its grown high enough.
|
||||
if self.hitpoints <= 0:
|
||||
damage_avg = self.node.damage_smoothed * damage_scale
|
||||
if damage_avg > 1000:
|
||||
@ -1144,23 +1145,23 @@ class Spaz(ba.Actor):
|
||||
return None
|
||||
node = ba.get_collision_info('opposing_node')
|
||||
|
||||
# only allow one hit per node per punch
|
||||
# Only allow one hit per node per punch.
|
||||
if node and (node not in self._punched_nodes):
|
||||
|
||||
punch_momentum_angular = (self.node.punch_momentum_angular *
|
||||
self._punch_power_scale)
|
||||
punch_power = self.node.punch_power * self._punch_power_scale
|
||||
|
||||
# ok here's the deal: we pass along our base velocity for use
|
||||
# Ok here's the deal: we pass along our base velocity for use
|
||||
# in the impulse damage calculations since that is a more
|
||||
# predictable value than our fist velocity, which is rather
|
||||
# erratic. ...however we want to actually apply force in the
|
||||
# direction our fist is moving so it looks better.. so we still
|
||||
# pass that along as a direction ..perhaps a time-averaged
|
||||
# fist-velocity would work too?.. should try that.
|
||||
# erratic. However, we want to actually apply force in the
|
||||
# direction our fist is moving so it looks better. So we still
|
||||
# pass that along as a direction. Perhaps a time-averaged
|
||||
# fist-velocity would work too?.. perhaps should try that.
|
||||
|
||||
# if its something besides another spaz, just do a muffled
|
||||
# punch sound
|
||||
# If its something besides another spaz, just do a muffled
|
||||
# punch sound.
|
||||
if node.getnodetype() != 'spaz':
|
||||
sounds = get_factory().impact_sounds_medium
|
||||
sound = sounds[random.randrange(len(sounds))]
|
||||
@ -1226,7 +1227,7 @@ class Spaz(ba.Actor):
|
||||
if held and held.getnodetype() == 'flag':
|
||||
return True
|
||||
|
||||
# hold_body needs to be set before hold_node.
|
||||
# Note: hold_body needs to be set before hold_node.
|
||||
self.node.hold_body = opposing_body
|
||||
self.node.hold_node = opposing_node
|
||||
elif isinstance(msg, ba.CelebrateMessage):
|
||||
@ -1280,7 +1281,8 @@ class Spaz(ba.Actor):
|
||||
|
||||
def _pick_up(self, node: ba.Node) -> None:
|
||||
if self.node:
|
||||
self.node.hold_body = 0 # needs to be set before hold_node
|
||||
# Note: hold_body needs to be set before hold_node.
|
||||
self.node.hold_body = 0
|
||||
self.node.hold_node = node
|
||||
|
||||
def set_land_mine_count(self, count: int) -> None:
|
||||
@ -1317,7 +1319,7 @@ class Spaz(ba.Actor):
|
||||
self.shattered = True
|
||||
assert self.node
|
||||
if self.frozen:
|
||||
# momentary flash of light
|
||||
# Momentary flash of light.
|
||||
light = ba.newnode('light',
|
||||
attrs={
|
||||
'position': self.node.position,
|
||||
@ -1333,7 +1335,8 @@ class Spaz(ba.Actor):
|
||||
0.3: 0
|
||||
})
|
||||
ba.timer(0.3, light.delete)
|
||||
# emit ice chunks..
|
||||
|
||||
# Emit ice chunks.
|
||||
ba.emitfx(position=self.node.position,
|
||||
velocity=self.node.velocity,
|
||||
count=int(random.random() * 10.0 + 10.0),
|
||||
@ -1399,8 +1402,8 @@ class Spaz(ba.Actor):
|
||||
|
||||
def set_bomb_count(self, count: int) -> None:
|
||||
"""Sets the number of bombs this Spaz has."""
|
||||
# we cant just set bomb_count cuz some bombs may be laid currently
|
||||
# so we have to do a relative diff based on max
|
||||
# We can't just set bomb_count because some bombs may be laid currently
|
||||
# so we have to do a relative diff based on max.
|
||||
diff = count - self._max_bomb_count
|
||||
self._max_bomb_count += diff
|
||||
self.bomb_count += diff
|
||||
@ -1413,7 +1416,7 @@ class Spaz(ba.Actor):
|
||||
self.node.billboard_cross_out = True
|
||||
|
||||
def _gloves_wear_off(self) -> None:
|
||||
if self._demo_mode: # preserve old behavior
|
||||
if self._demo_mode: # Preserve old behavior.
|
||||
self._punch_power_scale = 1.2
|
||||
self._punch_cooldown = BASE_PUNCH_COOLDOWN
|
||||
else:
|
||||
|
||||
@ -3730,7 +3730,7 @@ even if myactor is set to None.</p>
|
||||
</p>
|
||||
|
||||
<h3>Attributes:</h3>
|
||||
<h5><a href="#attr_ba_Player__node">node</a>, <a href="#attr_ba_Player__sessionplayer">sessionplayer</a></h5>
|
||||
<h5><a href="#attr_ba_Player__node">node</a>, <a href="#attr_ba_Player__position">position</a>, <a href="#attr_ba_Player__sessionplayer">sessionplayer</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="attr_ba_Player__node">node</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_Node">ba.Node</a></span></p>
|
||||
@ -3738,6 +3738,14 @@ even if myactor is set to None.</p>
|
||||
|
||||
<p> This node can be used to get a generic player position/etc.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Player__position">position</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_Vec3">ba.Vec3</a></span></p>
|
||||
<p>The position of the player, as defined by its current Actor.</p>
|
||||
|
||||
<p> This value should not be used when the player has no Actor, as
|
||||
it is undefined in that case.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Player__sessionplayer">sessionplayer</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_SessionPlayer">ba.SessionPlayer</a></span></p>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user