Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
ziqian zhang
Grasscutter
Commits
d7834852
Commit
d7834852
authored
May 08, 2022
by
gentlespoon
Committed by
Melledy
May 08, 2022
Browse files
Update StaminaManager
parent
a09723f0
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/game/managers/StaminaManager/AfterUpdateStaminaListener.java
0 → 100644
View file @
d7834852
package
emu.grasscutter.game.managers.StaminaManager
;
public
interface
AfterUpdateStaminaListener
{
/**
* onBeforeUpdateStamina() will be called before StaminaManager attempt to update the player's current stamina.
* This gives listeners a chance to intercept this update.
*
* @param reason Why updating stamina.
* @param newStamina New Stamina value.
*/
void
onAfterUpdateStamina
(
String
reason
,
int
newStamina
);
}
src/main/java/emu/grasscutter/game/managers/StaminaManager/BeforeUpdateStaminaListener.java
0 → 100644
View file @
d7834852
package
emu.grasscutter.game.managers.StaminaManager
;
public
interface
BeforeUpdateStaminaListener
{
/**
* onBeforeUpdateStamina() will be called before StaminaManager attempt to update the player's current stamina.
* This gives listeners a chance to intercept this update.
* @param reason Why updating stamina.
* @param newStamina New ABSOLUTE stamina value.
* @return true if you want to cancel this update, otherwise false.
*/
int
onBeforeUpdateStamina
(
String
reason
,
int
newStamina
);
/**
* onBeforeUpdateStamina() will be called before StaminaManager attempt to update the player's current stamina.
* This gives listeners a chance to intercept this update.
* @param reason Why updating stamina.
* @param consumption ConsumptionType and RELATIVE stamina change amount.
* @return true if you want to cancel this update, otherwise false.
*/
Consumption
onBeforeUpdateStamina
(
String
reason
,
Consumption
consumption
);
}
\ No newline at end of file
src/main/java/emu/grasscutter/game/managers/StaminaManager/ConsumptionType.java
View file @
d7834852
...
@@ -10,10 +10,10 @@ public enum ConsumptionType {
...
@@ -10,10 +10,10 @@ public enum ConsumptionType {
SPRINT
(-
1800
),
SPRINT
(-
1800
),
DASH
(-
360
),
DASH
(-
360
),
FLY
(-
60
),
FLY
(-
60
),
SWIM_DASH_START
(-
20
0
),
SWIM_DASH_START
(-
20
),
SWIM_DASH
(-
20
0
),
SWIM_DASH
(-
20
4
),
SWIMMING
(-
80
),
SWIMMING
(-
80
),
// TODO: Slow swimming is handled per movement, not per second. Movement frequency depends on gender/age/height.
FIGHT
(
0
),
FIGHT
(
0
),
// See StaminaManager.getFightConsumption()
// restore
// restore
STANDBY
(
500
),
STANDBY
(
500
),
...
...
src/main/java/emu/grasscutter/game/managers/StaminaManager/README.md
0 → 100644
View file @
d7834852
# Stamina Manager
---
## UpdateStamina
```
java
// will use consumption.consumptionType as reason
public
int
updateStaminaRelative
(
GameSession
session
,
Consumption
consumption
);
```
```
java
public
int
updateStaminaAbsolute
(
GameSession
session
,
String
reason
,
int
newStamina
)
```
---
## Pause and Resume
```
java
public
void
startSustainedStaminaHandler
()
```
```
java
public
void
stopSustainedStaminaHandler
()
```
---
## Stamina change listeners and intercepting
### BeforeUpdateStaminaListener
```
java
import
emu.grasscutter.game.managers.StaminaManager.BeforeUpdateStaminaListener
;
// Listener sample: plugin disable CLIMB_JUMP stamina cost.
private
class
MyClass
implements
BeforeUpdateStaminaListener
{
// Make your class implement the listener, and pass in your class as a listener.
public
MyClass
()
{
getStaminaManager
().
registerBeforeUpdateStaminaListener
(
"myClass"
,
this
);
}
@Override
public
boolean
onBeforeUpdateStamina
(
String
reason
,
int
newStamina
)
{
// do not intercept this update
return
false
;
}
@Override
public
boolean
onBeforeUpdateStamina
(
String
reason
,
Consumption
consumption
)
{
// Try to intercept if this update is CLIMB_JUMP
if
(
consumption
.
consumptionType
==
ConsumptionType
.
CLIMB_JUMP
)
{
return
true
;
}
// If it is not CLIMB_JUMP, do not intercept.
return
false
;
}
}
```
### AfterUpdateStaminaListener
```
java
import
emu.grasscutter.game.managers.StaminaManager.AfterUpdateStaminaListener
;
// Listener sample: plugin listens for changes already made.
private
class
MyClass
implements
AfterUpdateStaminaListener
{
// Make your class implement the listener, and pass in your class as a listener.
public
MyClass
()
{
registerAfterUpdateStaminaListener
(
"myClass"
,
this
);
}
@Override
public
void
onAfterUpdateStamina
(
String
reason
,
int
newStamina
)
{
// ...
}
}
```
\ No newline at end of file
src/main/java/emu/grasscutter/game/managers/StaminaManager/StaminaManager.java
View file @
d7834852
This diff is collapsed.
Click to expand it.
src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java
View file @
d7834852
...
@@ -49,22 +49,23 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
...
@@ -49,22 +49,23 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
session
.
getPlayer
().
getStaminaManager
().
handleCombatInvocationsNotify
(
session
,
moveInfo
,
entity
);
session
.
getPlayer
().
getStaminaManager
().
handleCombatInvocationsNotify
(
session
,
moveInfo
,
entity
);
// TODO: handle MOTION_FIGHT landing
// TODO: handle MOTION_FIGHT landing
which has a different damage factor
//
F
or plunge attacks, LAND_SPEED is always -30 and is not useful.
//
Also, f
or plunge attacks, LAND_SPEED is always -30 and is not useful.
// May need the height when starting plunge attack.
//
May need the height when starting plunge attack.
// MOTION_LAND_SPEED and MOTION_FALL_ON_GROUND arrive in different packets.
// Cache land speed for later use.
if
(
motionState
==
MotionState
.
MOTION_LAND_SPEED
)
{
cachedLandingSpeed
=
motionInfo
.
getSpeed
().
getY
();
cachedLandingTimeMillisecond
=
System
.
currentTimeMillis
();
monitorLandingEvent
=
true
;
}
if
(
monitorLandingEvent
)
{
if
(
monitorLandingEvent
)
{
if
(
motionState
==
MotionState
.
MOTION_FALL_ON_GROUND
)
{
if
(
motionState
==
MotionState
.
MOTION_FALL_ON_GROUND
)
{
monitorLandingEvent
=
false
;
monitorLandingEvent
=
false
;
handleFallOnGround
(
session
,
entity
,
motionState
);
handleFallOnGround
(
session
,
entity
,
motionState
);
}
}
}
}
if
(
motionState
==
MotionState
.
MOTION_LAND_SPEED
)
{
// MOTION_LAND_SPEED and MOTION_FALL_ON_GROUND arrive in different packet. Cache land speed for later use.
cachedLandingSpeed
=
motionInfo
.
getSpeed
().
getY
();
cachedLandingTimeMillisecond
=
System
.
currentTimeMillis
();
monitorLandingEvent
=
true
;
}
}
}
break
;
break
;
default
:
default
:
...
@@ -84,33 +85,42 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
...
@@ -84,33 +85,42 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
}
}
private
void
handleFallOnGround
(
GameSession
session
,
GameEntity
entity
,
MotionState
motionState
)
{
private
void
handleFallOnGround
(
GameSession
session
,
GameEntity
entity
,
MotionState
motionState
)
{
// If not received immediately after MOTION_LAND_SPEED, discard this packet.
// People have reported that after plunge attack (client sends a FIGHT instead of FALL_ON_GROUND) they will die
// if they talk to an NPC (this is when the client sends a FALL_ON_GROUND) without jumping again.
// A dirty patch: if not received immediately after MOTION_LAND_SPEED, discard this packet.
// 200ms seems to be a reasonable delay.
int
maxDelay
=
200
;
int
maxDelay
=
200
;
long
actualDelay
=
System
.
currentTimeMillis
()
-
cachedLandingTimeMillisecond
;
long
actualDelay
=
System
.
currentTimeMillis
()
-
cachedLandingTimeMillisecond
;
Grasscutter
.
getLogger
().
debug
(
"MOTION_FALL_ON_GROUND received after "
+
actualDelay
+
"/"
+
maxDelay
+
"ms."
+
(
actualDelay
>
maxDelay
?
" Discard"
:
""
));
Grasscutter
.
getLogger
().
trace
(
"MOTION_FALL_ON_GROUND received after "
+
actualDelay
+
"/"
+
maxDelay
+
"ms."
+
(
actualDelay
>
maxDelay
?
" Discard"
:
""
));
if
(
actualDelay
>
maxDelay
)
{
if
(
actualDelay
>
maxDelay
)
{
return
;
return
;
}
}
float
currentHP
=
entity
.
getFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
);
float
currentHP
=
entity
.
getFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
);
float
maxHP
=
entity
.
getFightProperty
(
FightProperty
.
FIGHT_PROP_MAX_HP
);
float
maxHP
=
entity
.
getFightProperty
(
FightProperty
.
FIGHT_PROP_MAX_HP
);
float
damage
=
0
;
float
damage
Factor
=
0
;
if
(
cachedLandingSpeed
<
-
23.5
)
{
if
(
cachedLandingSpeed
<
-
23.5
)
{
damage
=
(
float
)
(
maxHP
*
0.33
)
;
damage
Factor
=
0.33
f
;
}
}
if
(
cachedLandingSpeed
<
-
25
)
{
if
(
cachedLandingSpeed
<
-
25
)
{
damage
=
(
float
)
(
maxHP
*
0.5
)
;
damage
Factor
=
0.5
f
;
}
}
if
(
cachedLandingSpeed
<
-
26.5
)
{
if
(
cachedLandingSpeed
<
-
26.5
)
{
damage
=
(
float
)
(
maxHP
*
0.66
)
;
damage
Factor
=
0.66
f
;
}
}
if
(
cachedLandingSpeed
<
-
28
)
{
if
(
cachedLandingSpeed
<
-
28
)
{
damage
=
(
maxHP
*
1
)
;
damage
Factor
=
1
f
;
}
}
float
damage
=
maxHP
*
damageFactor
;
float
newHP
=
currentHP
-
damage
;
float
newHP
=
currentHP
-
damage
;
if
(
newHP
<
0
)
{
if
(
newHP
<
0
)
{
newHP
=
0
;
newHP
=
0
;
}
}
Grasscutter
.
getLogger
().
debug
(
currentHP
+
"/"
+
maxHP
+
"\t"
+
"\tDamage: "
+
damage
+
"\tnewHP: "
+
newHP
);
if
(
damageFactor
>
0
)
{
Grasscutter
.
getLogger
().
debug
(
currentHP
+
"/"
+
maxHP
+
"\tLandingSpeed: "
+
cachedLandingSpeed
+
"\tDamageFactor: "
+
damageFactor
+
"\tDamage: "
+
damage
+
"\tNewHP: "
+
newHP
);
}
else
{
Grasscutter
.
getLogger
().
trace
(
currentHP
+
"/"
+
maxHP
+
"\tLandingSpeed: 0\tNo damage"
);
}
entity
.
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
newHP
);
entity
.
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
newHP
);
entity
.
getWorld
().
broadcastPacket
(
new
PacketEntityFightPropUpdateNotify
(
entity
,
FightProperty
.
FIGHT_PROP_CUR_HP
));
entity
.
getWorld
().
broadcastPacket
(
new
PacketEntityFightPropUpdateNotify
(
entity
,
FightProperty
.
FIGHT_PROP_CUR_HP
));
if
(
newHP
==
0
)
{
if
(
newHP
==
0
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment