Pre-menu-integration snapshot: combat, crafting, status effects, gamedata updates
This commit is contained in:
@@ -208,8 +208,18 @@ async def execute_attack(
|
||||
broken_armor = []
|
||||
|
||||
if is_pvp:
|
||||
is_defending = False
|
||||
target_effects = await db.get_player_effects(target['id'])
|
||||
defending_effect = next((e for e in target_effects if e['effect_name'] == 'defending'), None)
|
||||
if defending_effect:
|
||||
is_defending = True
|
||||
reduction = defending_effect.get('value', 50) / 100
|
||||
damage = max(1, int(damage * (1 - reduction)))
|
||||
messages.append(create_combat_message("damage_reduced", origin="enemy", reduction=int(reduction * 100)))
|
||||
await db.remove_effect(target['id'], 'defending')
|
||||
|
||||
# PvP: use equipment-based armor reduction + durability
|
||||
armor_absorbed, broken_armor = await reduce_armor_func(target['id'], damage)
|
||||
armor_absorbed, broken_armor = await reduce_armor_func(target['id'], damage, is_defending)
|
||||
actual_damage = max(1, damage - armor_absorbed)
|
||||
else:
|
||||
# PvE: use NPC's flat defense value
|
||||
@@ -279,6 +289,54 @@ async def execute_attack(
|
||||
}
|
||||
|
||||
|
||||
async def execute_defend(
|
||||
player_id: int,
|
||||
player: dict,
|
||||
player_stats: dict,
|
||||
is_pvp: bool,
|
||||
locale: str = 'en'
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Execute a defend action.
|
||||
Reduces incoming damage by 50% for the next turn, but increases durability loss.
|
||||
|
||||
Returns: {
|
||||
messages: list
|
||||
}
|
||||
"""
|
||||
from .. import database as db
|
||||
from .helpers import create_combat_message, get_game_message
|
||||
|
||||
messages = []
|
||||
|
||||
# 5% Stamina restore
|
||||
stamina_restore = max(5, int(player_stats.get('max_stamina', 100) * 0.05))
|
||||
new_stamina = min(player_stats.get('max_stamina', 100), player.get('stamina', 100) + stamina_restore)
|
||||
await db.update_player(player_id, stamina=new_stamina)
|
||||
|
||||
# Add defending effect
|
||||
await db.add_effect(
|
||||
player_id=player_id,
|
||||
effect_name="defending",
|
||||
effect_icon="🛡️",
|
||||
effect_type="buff",
|
||||
ticks_remaining=1,
|
||||
persist_after_combat=False,
|
||||
source="combat_defend",
|
||||
value=50 # 50% reduction
|
||||
)
|
||||
|
||||
messages.append(create_combat_message(
|
||||
"player_defend",
|
||||
origin="player"
|
||||
))
|
||||
|
||||
return {
|
||||
'messages': messages,
|
||||
'stamina_restored': stamina_restore,
|
||||
}
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# SKILL ACTION
|
||||
# ============================================================================
|
||||
@@ -294,6 +352,7 @@ async def execute_skill(
|
||||
items_manager: ItemsManager,
|
||||
reduce_armor_func,
|
||||
redis_manager=None,
|
||||
locale: str = 'en'
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Execute a skill action. Validates requirements, deducts stamina, applies effects.
|
||||
@@ -402,6 +461,17 @@ async def execute_skill(
|
||||
if effects.get('guaranteed_crit'):
|
||||
damage = int(damage * player_stats.get('crit_damage', 1.5))
|
||||
|
||||
is_defending = False
|
||||
if is_pvp:
|
||||
target_effects = await db.get_player_effects(target['id'])
|
||||
defending_effect = next((e for e in target_effects if e['effect_name'] == 'defending'), None)
|
||||
if defending_effect:
|
||||
is_defending = True
|
||||
reduction = defending_effect.get('value', 50) / 100
|
||||
damage = max(1, int(damage * (1 - reduction)))
|
||||
messages.append(create_combat_message("damage_reduced", origin="enemy", reduction=int(reduction * 100)))
|
||||
await db.remove_effect(target['id'], 'defending')
|
||||
|
||||
# Multi-hit
|
||||
num_hits = effects.get('hits', 1)
|
||||
total_damage = 0
|
||||
@@ -412,7 +482,7 @@ async def execute_skill(
|
||||
|
||||
if is_pvp:
|
||||
# PvP: armor from equipment
|
||||
absorbed, broken_armor = await reduce_armor_func(target['id'], hit_dmg)
|
||||
absorbed, broken_armor = await reduce_armor_func(target['id'], hit_dmg, is_defending)
|
||||
total_armor_absorbed += absorbed
|
||||
for broken in broken_armor:
|
||||
messages.append(create_combat_message(
|
||||
@@ -450,8 +520,11 @@ async def execute_skill(
|
||||
"skill_heal", origin="player", heal=heal_amount, skill_icon="🩸"
|
||||
))
|
||||
|
||||
from .helpers import calculate_dynamic_status_damage
|
||||
# Poison DoT
|
||||
if 'poison_damage' in effects:
|
||||
poison_dmg = calculate_dynamic_status_damage(effects, 'poison', target)
|
||||
if poison_dmg is not None:
|
||||
poison_dur = effects.get('poison_duration', 3)
|
||||
if is_pvp:
|
||||
# PvP: add as player effect
|
||||
await db.add_effect(
|
||||
@@ -459,14 +532,14 @@ async def execute_skill(
|
||||
effect_name="Poison",
|
||||
effect_icon="🧪",
|
||||
effect_type="damage",
|
||||
damage_per_tick=effects['poison_damage'],
|
||||
ticks_remaining=effects['poison_duration'],
|
||||
damage_per_tick=poison_dmg,
|
||||
ticks_remaining=poison_dur,
|
||||
persist_after_combat=True,
|
||||
source=f"skill_poison:{skill.id}"
|
||||
)
|
||||
else:
|
||||
# PvE: add to npc_status_effects string
|
||||
poison_str = f"poison:{effects['poison_damage']}:{effects['poison_duration']}"
|
||||
poison_str = f"poison:{poison_dmg}:{poison_dur}"
|
||||
existing = combat_state.get('npc_status_effects', '') or ''
|
||||
if existing:
|
||||
existing += '|' + poison_str
|
||||
@@ -476,7 +549,38 @@ async def execute_skill(
|
||||
|
||||
messages.append(create_combat_message(
|
||||
"skill_effect", origin="player",
|
||||
message=f"🧪 Poisoned! ({effects['poison_damage']} dmg/turn)"
|
||||
message=f"🧪 Poisoned! ({poison_dmg} dmg/turn)"
|
||||
))
|
||||
|
||||
# Burn DoT
|
||||
burn_dmg = calculate_dynamic_status_damage(effects, 'burn', target)
|
||||
if burn_dmg is not None:
|
||||
burn_dur = effects.get('burn_duration', 3)
|
||||
if is_pvp:
|
||||
# PvP: add as player effect
|
||||
await db.add_effect(
|
||||
player_id=target['id'],
|
||||
effect_name="Burning",
|
||||
effect_icon="🔥",
|
||||
effect_type="damage",
|
||||
damage_per_tick=burn_dmg,
|
||||
ticks_remaining=burn_dur,
|
||||
persist_after_combat=True,
|
||||
source=f"skill_burn:{skill.id}"
|
||||
)
|
||||
else:
|
||||
# PvE: add to npc_status_effects string
|
||||
burn_str = f"burning:{burn_dmg}:{burn_dur}"
|
||||
existing = combat_state.get('npc_status_effects', '') or ''
|
||||
if existing:
|
||||
existing += '|' + burn_str
|
||||
else:
|
||||
existing = burn_str
|
||||
await db.update_combat(player_id, {'npc_status_effects': existing})
|
||||
|
||||
messages.append(create_combat_message(
|
||||
"skill_effect", origin="player",
|
||||
message=f"🔥 Burning! ({burn_dmg} dmg/turn)"
|
||||
))
|
||||
|
||||
# Stun chance
|
||||
@@ -506,7 +610,7 @@ async def execute_skill(
|
||||
await db.update_combat(player_id, {'npc_status_effects': existing})
|
||||
|
||||
messages.append(create_combat_message(
|
||||
"skill_effect", origin="player", message="💫 Stunned!"
|
||||
"skill_effect", origin="player", message=get_game_message('stunned_status', locale)
|
||||
))
|
||||
|
||||
# Weapon durability
|
||||
@@ -721,7 +825,13 @@ async def execute_use_item(
|
||||
# 6. Status effect on target (burn from molotov etc.) — PvE only
|
||||
status_effect = combat_effects.get('status') if not is_pvp else None
|
||||
if status_effect and not target_defeated:
|
||||
npc_status = f"{status_effect['name']}:{status_effect.get('damage_per_tick', 0)}:{status_effect.get('ticks', 1)}"
|
||||
dmg = status_effect.get('damage_per_tick', 0)
|
||||
if 'damage_percent' in status_effect:
|
||||
max_hp = target.get('npc_max_hp', target.get('max_hp', 100))
|
||||
base_dmg = max_hp * status_effect['damage_percent']
|
||||
dmg = random.randint(max(1, int(base_dmg * 0.8)), max(1, int(base_dmg * 1.2)))
|
||||
|
||||
npc_status = f"{status_effect['name']}:{dmg}:{status_effect.get('ticks', 1)}"
|
||||
await db.update_combat(player_id, {'npc_status_effects': npc_status})
|
||||
messages.append(create_combat_message(
|
||||
"effect_applied", origin="player",
|
||||
@@ -1123,6 +1233,7 @@ async def execute_npc_turn(
|
||||
npc_def,
|
||||
reduce_armor_func,
|
||||
redis_manager=None,
|
||||
locale: str = 'en'
|
||||
) -> Tuple[List[dict], bool]:
|
||||
"""
|
||||
Execute the NPC's turn with buff-aware damage reduction.
|
||||
@@ -1145,7 +1256,7 @@ async def execute_npc_turn(
|
||||
|
||||
from ..game_logic import npc_attack
|
||||
messages, player_defeated = await npc_attack(
|
||||
player_id, combat, npc_def, reduce_armor_func, player_stats=stats
|
||||
player_id, combat, npc_def, reduce_armor_func, player_stats=stats, locale=locale
|
||||
)
|
||||
|
||||
return messages, player_defeated
|
||||
|
||||
Reference in New Issue
Block a user