doomsday: Redo the M&S stomp attack.

This commit is contained in:
Sam Edwards 2014-04-18 22:02:48 -06:00
parent f9ae4556f1
commit d7490bf7a1
3 changed files with 171 additions and 17 deletions

View file

@ -0,0 +1,36 @@
import random
from otp.ai.MagicWordGlobal import *
class ShakeCamera:
def __init__(self, intensity, duration=0.5, rate=30.0):
self.intensity = intensity
self.duration = duration
self.rate = rate
self.elapsed = 0.0
def start(self):
taskMgr.add(self.__task, 'shakeCamera')
def __task(self, task):
random_x = random.random()*2 - 1
random_z = random.random()*2 - 1
lifecycle = self.elapsed / self.duration
if lifecycle > 1.0:
base.cam.setPos(0, 0, 0)
return task.done
displacement = (1-lifecycle) * self.intensity
base.cam.setPos(random_x * displacement, 0, random_z * displacement)
task.delayTime = 1.0/self.rate
self.elapsed += 1.0/self.rate
return task.again
@magicWord(category=CATEGORY_GRAPHICAL, types=[float])
def shakeCamera(intensity):
"""Momentarily shake the camera, as if something heavy went bump nearby."""
sc = ShakeCamera(intensity)
sc.start()

View file

@ -12,6 +12,7 @@ from InvasionSuitBase import InvasionSuitBase
from toontown.distributed.DelayDeletable import DelayDeletable
from toontown.distributed.DelayDelete import *
import random
from ThumpAttack import ThumpAttack
class DistributedInvasionSuit(DistributedSuitBase, InvasionSuitBase, FSM, DelayDeletable):
def __init__(self, cr):
@ -53,11 +54,8 @@ class DistributedInvasionSuit(DistributedSuitBase, InvasionSuitBase, FSM, DelayD
# Get a few things defined for our Shakers
self.shakerRadialAttack = None
self.stompSfx = loader.loadSfx('phase_5/audio/sfx/SA_tremor.ogg')
self.msStartStomp = Sequence(
Func(self.play, 'walk', fromFrame=0, toFrame=22),
Wait(0.9),
Func(self.loop, 'walk', fromFrame=22, toFrame=62)
)
self.msStompLoop = None
self.msStartStomp = None
self.msSoundLoop = Sequence(SoundInterval(self.stompSfx, duration=1.6, startTime=0.3, volume=0.4, node=self))
def announceGenerate(self):
@ -143,18 +141,20 @@ class DistributedInvasionSuit(DistributedSuitBase, InvasionSuitBase, FSM, DelayD
def enterMarch(self, time):
if self.style.name == 'ms':
self.__stompGenerate()
self.msStartStomp.start(time)
self.msSoundLoop.loop(time)
self.shakerRadialAttack = taskMgr.add(self.__checkToonsInRadius, self.uniqueName('ShakerAttack'))
else:
self.loop('walk', 0)
self.startMoveTask()
def exitMarch(self):
if self.msStartStomp.isPlaying():
if self.msStartStomp and self.msStartStomp.isPlaying():
self.msStartStomp.finish()
if self.msSoundLoop.isPlaying():
self.msSoundLoop.finish()
if self.msStompLoop and self.msStompLoop.isPlaying():
self.msStompLoop.finish()
self.loop('neutral', 0)
self.stopMoveTask()
self.stopShakerRadialAttack()
@ -162,7 +162,7 @@ class DistributedInvasionSuit(DistributedSuitBase, InvasionSuitBase, FSM, DelayD
def enterAttack(self, time):
if self.style.name == 'ms':
self.shakerRadialAttack = taskMgr.add(self.__checkToonsInRadius, self.uniqueName('ShakerAttack'))
self.__stompGenerate()
self.msStartStomp.start(time)
self.msSoundLoop.loop(time)
return
@ -174,10 +174,12 @@ class DistributedInvasionSuit(DistributedSuitBase, InvasionSuitBase, FSM, DelayD
self._attackInterval.pause()
self.cleanupProp(self._attackInterval.prop, self._attackInterval.propIsActor)
#hehehe manual cleanup. so bad
if self.msStartStomp.isPlaying():
if self.msStartStomp and self.msStartStomp.isPlaying():
self.msStartStomp.finish()
if self.msSoundLoop.isPlaying():
self.msSoundLoop.finish()
if self.msStompLoop and self.msStompLoop.isPlaying():
self.msStompLoop.finish()
self.stopShakerRadialAttack()
def setAttackInfo(self, targetId, attackProp, attackDamage):
@ -458,15 +460,35 @@ class DistributedInvasionSuit(DistributedSuitBase, InvasionSuitBase, FSM, DelayD
if toon.hp > 0:
base.localAvatar.enableAvatarControls()
def __checkToonsInRadius(self, task):
def __stomp(self):
if self.exploding:
return task.done
return
ta = ThumpAttack(lambda: \
self.applyShakeAttack(base.localAvatar,
SafezoneInvasionGlobals.MoveShakerDamageRadius)
)
ta.reparentTo(self.getParent())
ta.setPos(self, 0, 0, 0)
ta.start()
def __stompGenerate(self):
if not self.msStompLoop:
self.msStompLoop = Sequence(
ActorInterval(self, 'walk', startFrame=22, endFrame=39),
Func(self.__stomp),
ActorInterval(self, 'walk', startFrame=39, endFrame=59),
Func(self.__stomp),
ActorInterval(self, 'walk', startFrame=59, endFrame=62)
)
if not self.msStartStomp:
self.msStartStomp = Sequence(
Func(self.play, 'walk', fromFrame=0, toFrame=22),
Wait(0.9),
Func(self.msStompLoop.loop)
)
toon = base.localAvatar
if toon:
if Vec3(toon.getPos(self)).length() <= SafezoneInvasionGlobals.MoveShakerRadius:
self.applyShakeAttack(toon, SafezoneInvasionGlobals.MoveShakerDamageRadius)
return task.cont
def applyShakeAttack(self, toon, damage):
if not getattr(localAvatar.controlManager.currentControls, 'isAirborne', 0):
@ -595,4 +617,4 @@ class DistributedInvasionSuit(DistributedSuitBase, InvasionSuitBase, FSM, DelayD
def exitFinaleStompAttack(self):
self.finaleAttackJump.finish()
self.finaleStompSequence.finish()
self.finaleStompSequence.finish()

View file

@ -0,0 +1,96 @@
from panda3d.core import *
from direct.showbase.DirectObject import DirectObject
from direct.interval.IntervalGlobal import *
from otp.ai.MagicWordGlobal import *
from toontown.toonbase import ToontownGlobals
from toontown.effects.ShakeCamera import ShakeCamera
import SafezoneInvasionGlobals
class ThumpAttack(NodePath, DirectObject):
SPEED = 10.0
RANGE = SafezoneInvasionGlobals.MoveShakerRadius
FADE_TIME = 0.2
INNER_RADIUS = 0.95 # Only outer 5% of the shockwave shell counts.
SHAKE_INTENSITY = 64.0 # How dizzy we get from this thump.
cm = CardMaker('thump_geom')
cm.setFrame(-1, 1, -1, 1)
def __init__(self, callback):
NodePath.__init__(self, 'thump')
DirectObject.__init__(self)
self.geom = self.attachNewNode(self.cm.generate())
self.geom.setP(-90)
self.geom.setTransparency(1)
self.geom.setDepthWrite(0)
self.geom.setDepthTest(0)
self.geom.setBin('shadow', 0)
self.collisionName = 'thumpCollide-%d' % id(self)
self.collision = self.attachNewNode(CollisionNode(self.collisionName))
csphere = CollisionSphere(0,0,0,1)
csphere.setTangible(0)
self.collision.node().addSolid(csphere)
self.collision.node().setIntoCollideMask(ToontownGlobals.WallBitmask)
self.callback = callback
def start(self):
spreadTime = self.RANGE/self.SPEED
interval = Sequence(
Parallel(
LerpScaleInterval(self, spreadTime,
self.RANGE, startScale=0),
Sequence(
Wait(spreadTime - self.FADE_TIME),
LerpColorScaleInterval(self, self.FADE_TIME, (1,1,1,0))
)
),
Func(self.cleanup)
)
offset = base.localAvatar.getPos(render) - self.getPos(render)
intensity = self.SHAKE_INTENSITY/offset.lengthSquared()
shake = ShakeCamera(intensity)
shake.start()
interval.start()
self.accept('enter' + self.collisionName, self.__handleCollide)
self.accept('again' + self.collisionName, self.__handleCollide)
def __handleCollide(self, ce):
# Find out how far base.localAvatar is within us:
offset = base.localAvatar.getPos(self) - Point3(0, 0, 0)
if offset.lengthSquared() < self.INNER_RADIUS*self.INNER_RADIUS:
return # Too far inside, not on the front of the shockwave.
# Are they on the ground?
if getattr(base.localAvatar.controlManager.currentControls, 'isAirborne', 0):
return # Yeah, we're safe.
self.ignoreAll() # Ignore subsequent collisions.
self.callback()
def cleanup(self):
self.ignoreAll()
self.removeNode()
@magicWord(category=CATEGORY_DEBUG)
def doThump():
"""Plays a 'thump attack' effect in front of your current position."""
thump = ThumpAttack(lambda: base.localAvatar.setSystemMessage(0, 'Gotcha!'))
thump.setPos(spellbook.getInvoker(), 0, 5, 0)
thump.reparentTo(render)
thump.start()