Clean repo for open source release
Remove build artifacts, dev tool configs, unused dependencies, and third-party source dumps. Add proper README, update .gitignore, clean up Makefile.
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
package com.tiedup.remake.state.struggle;
|
||||
|
||||
import com.tiedup.remake.core.SystemMessageManager;
|
||||
import com.tiedup.remake.core.SystemMessageManager.MessageCategory;
|
||||
import com.tiedup.remake.core.TiedUpMod;
|
||||
import com.tiedup.remake.state.PlayerBindState;
|
||||
import com.tiedup.remake.core.SettingsAccessor;
|
||||
import com.tiedup.remake.util.time.Timer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
|
||||
/**
|
||||
* Phase 7: Base class for struggle mechanics.
|
||||
*
|
||||
* Handles the logic for players/NPCs struggling against restraints:
|
||||
* - Cooldown timer between attempts
|
||||
* - Probability-based success (dice roll)
|
||||
* - Resistance decrease on success
|
||||
* - Automatic removal when resistance reaches 0
|
||||
*
|
||||
* v2.5: This is now used for NPC struggle only.
|
||||
* Players use the continuous struggle mini-game (ContinuousStruggleMiniGameState).
|
||||
* Knife bonuses have been removed - knives now work by active cutting.
|
||||
*
|
||||
* Architecture:
|
||||
* - StruggleState (abstract base)
|
||||
* ├─ StruggleBinds (struggle against bind restraints)
|
||||
* └─ StruggleCollar (struggle against collar/ownership)
|
||||
*/
|
||||
public abstract class StruggleState {
|
||||
|
||||
/**
|
||||
* Cooldown timer for struggle attempts.
|
||||
* Reset after each struggle attempt.
|
||||
* Volatile for thread safety across network/tick threads.
|
||||
*/
|
||||
protected volatile Timer struggleCooldownTimer;
|
||||
|
||||
/**
|
||||
* Main struggle logic (dice roll based).
|
||||
* Used for NPC struggle - players use QTE mini-game instead.
|
||||
*
|
||||
* Flow:
|
||||
* 1. Check if struggle is enabled (GameRule)
|
||||
* 2. Check if item can be struggled out of
|
||||
* 3. Check cooldown timer
|
||||
* 4. Roll dice for success (probability %)
|
||||
* 5. If success: decrease resistance by random amount
|
||||
* 6. If resistance <= 0: call successAction()
|
||||
* 7. Set cooldown for next attempt
|
||||
*
|
||||
* @param state The player's bind state
|
||||
*/
|
||||
public synchronized void struggle(PlayerBindState state) {
|
||||
Player player = state.getPlayer();
|
||||
if (player == null || player.level() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameRules gameRules = player.level().getGameRules();
|
||||
|
||||
// 1. Check if struggle system is enabled
|
||||
if (!SettingsAccessor.isStruggleEnabled(gameRules)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Check if item can be struggled out of (not locked or forced)
|
||||
if (!canStruggle(state)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Check cooldown timer (prevent spamming)
|
||||
if (
|
||||
struggleCooldownTimer != null && !struggleCooldownTimer.isExpired()
|
||||
) {
|
||||
TiedUpMod.LOGGER.debug(
|
||||
"[STRUGGLE] Cooldown not expired yet - ignoring struggle attempt"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Start struggle animation (after cooldown check passes)
|
||||
if (!state.isStruggling()) {
|
||||
state.setStruggling(true, player.level().getGameTime());
|
||||
com.tiedup.remake.network.sync.SyncManager.syncStruggleState(
|
||||
player
|
||||
);
|
||||
}
|
||||
|
||||
// Phase 13: Trigger attempt effects (shock collar check)
|
||||
if (!onAttempt(state)) {
|
||||
return; // Interrupted by pain
|
||||
}
|
||||
|
||||
// 4. Roll for success
|
||||
int probability = SettingsAccessor.getProbabilityStruggle(gameRules);
|
||||
int roll = player.getRandom().nextInt(100) + 1;
|
||||
boolean success = roll <= probability;
|
||||
|
||||
if (success) {
|
||||
// Calculate resistance decrease
|
||||
int currentResistance = getResistanceState(state);
|
||||
int minDecrease = SettingsAccessor.getStruggleMinDecrease(gameRules);
|
||||
int maxDecrease = SettingsAccessor.getStruggleMaxDecrease(gameRules);
|
||||
|
||||
int decrease =
|
||||
minDecrease +
|
||||
player.getRandom().nextInt(maxDecrease - minDecrease + 1);
|
||||
|
||||
int newResistance = Math.max(0, currentResistance - decrease);
|
||||
setResistanceState(state, newResistance);
|
||||
|
||||
// Feedback
|
||||
notifySuccess(player, newResistance);
|
||||
|
||||
// Check for escape
|
||||
if (newResistance <= 0) {
|
||||
TiedUpMod.LOGGER.debug(
|
||||
"[STRUGGLE] {} broke free! (resistance reached 0)",
|
||||
player.getName().getString()
|
||||
);
|
||||
successAction(state);
|
||||
}
|
||||
} else {
|
||||
notifyFailure(player);
|
||||
}
|
||||
|
||||
// 5. Set cooldown
|
||||
int cooldownTicks = SettingsAccessor.getStruggleTimer(gameRules);
|
||||
struggleCooldownTimer = new Timer(cooldownTicks / 20, player.level());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message category for successful struggle attempts.
|
||||
*/
|
||||
protected abstract MessageCategory getSuccessCategory();
|
||||
|
||||
/**
|
||||
* Get the message category for failed struggle attempts.
|
||||
*/
|
||||
protected abstract MessageCategory getFailCategory();
|
||||
|
||||
/**
|
||||
* Send success notification to the player.
|
||||
*
|
||||
* @param player The player to notify
|
||||
* @param newResistance The new resistance value after decrease
|
||||
*/
|
||||
protected void notifySuccess(Player player, int newResistance) {
|
||||
SystemMessageManager.sendWithResistance(
|
||||
player,
|
||||
getSuccessCategory(),
|
||||
newResistance
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send failure notification to the player.
|
||||
*
|
||||
* @param player The player to notify
|
||||
*/
|
||||
protected void notifyFailure(Player player) {
|
||||
SystemMessageManager.sendToPlayer(player, getFailCategory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the player successfully struggles free (resistance reaches 0).
|
||||
* Subclasses implement this to handle the escape action.
|
||||
*
|
||||
* @param state The player's bind state
|
||||
*/
|
||||
protected abstract void successAction(PlayerBindState state);
|
||||
|
||||
/**
|
||||
* Called when a struggle attempt is performed (regardless of success/fail).
|
||||
* Can be used for side effects like random shocks.
|
||||
*
|
||||
* @param state The player's bind state
|
||||
* @return true to proceed with struggle, false to interrupt
|
||||
*/
|
||||
protected boolean onAttempt(PlayerBindState state) {
|
||||
return true; // Default: proceed
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current resistance value from the player's state.
|
||||
*
|
||||
* @param state The player's bind state
|
||||
* @return Current resistance value
|
||||
*/
|
||||
protected abstract int getResistanceState(PlayerBindState state);
|
||||
|
||||
/**
|
||||
* Set the current resistance value in the player's state.
|
||||
*
|
||||
* @param state The player's bind state
|
||||
* @param resistance The new resistance value
|
||||
*/
|
||||
protected abstract void setResistanceState(
|
||||
PlayerBindState state,
|
||||
int resistance
|
||||
);
|
||||
|
||||
/**
|
||||
* Check if the player can struggle.
|
||||
* Returns false if the item cannot be struggled out of.
|
||||
*
|
||||
* @param state The player's bind state
|
||||
* @return True if struggling is allowed
|
||||
*/
|
||||
protected abstract boolean canStruggle(PlayerBindState state);
|
||||
|
||||
/**
|
||||
* Check if the item being struggled against is locked.
|
||||
*
|
||||
* @param state The player's bind state
|
||||
* @return true if the item is locked
|
||||
*/
|
||||
protected boolean isItemLocked(PlayerBindState state) {
|
||||
return false; // Default: not locked, subclasses override
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if debug logging is enabled.
|
||||
*
|
||||
* @return True if debug logging should be printed
|
||||
*/
|
||||
protected boolean isDebugEnabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user