91 lines
3.8 KiB
Python
91 lines
3.8 KiB
Python
# -*- coding: utf-8 -*-
|
||
#
|
||
# 医疗物品:自定义蓄力物品(custom_item_type: ranged_weapon)
|
||
# 右键按下开始蓄力,右键抬起触发 ItemReleaseUsingServerEvent;
|
||
# 蓄满才生效并消耗 1 个,未蓄满松开则取消(不生效、不消耗)。
|
||
import mod.server.extraServerApi as serverApi
|
||
|
||
compFactory = serverApi.GetEngineCompFactory()
|
||
|
||
PLASTER = "dn_sa_plaster:bow"
|
||
SPLINT = "dn_sa_splint:bow"
|
||
ALCOHOL_WIPES = "dn_sa_alcohol_wipes:bow"
|
||
BLOOD_BAG = "dn_sa:blood_bag"
|
||
BLOOD_BAG_EMPTY = "dn_sa:blood_bag_empty"
|
||
|
||
# 蓄满所需持有时长(tick,20 tick = 1 秒)
|
||
CHARGE_TICKS = 60
|
||
CHARGE_ITEMS = (PLASTER, SPLINT, ALCOHOL_WIPES)
|
||
|
||
HEAL_AMOUNT = 6.0 # 血袋回血量
|
||
DONATE_TOTAL = 6 # 空血袋总扣血量
|
||
DONATE_STEP = 1.0 # 每次扣血量
|
||
DONATE_INTERVAL = 0.5 # 扣血间隔秒数
|
||
|
||
|
||
class MedicalServer(serverApi.GetServerSystemCls()):
|
||
def __init__(self, namespace, name):
|
||
super(MedicalServer, self).__init__(namespace, name)
|
||
self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(),
|
||
"ItemReleaseUsingServerEvent", self, self.OnReleaseUsing)
|
||
self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(),
|
||
"PlayerEatFoodServerEvent", self, self.OnEatFood)
|
||
|
||
# ---------- 蓄力物品 ----------
|
||
def OnReleaseUsing(self, args):
|
||
playerId = args.get("playerId")
|
||
itemName = (args.get("itemDict") or {}).get("itemName")
|
||
if not playerId or itemName not in CHARGE_ITEMS:
|
||
return
|
||
# 已持有帧数 = 最大使用时长 - 剩余时长
|
||
maxUse = args.get("maxUseDuration") or 0
|
||
durationLeft = args.get("durationLeft") or 0
|
||
held = (maxUse - durationLeft) if maxUse > 0 else CHARGE_TICKS
|
||
# 未蓄满:取消本次使用
|
||
if held < CHARGE_TICKS:
|
||
args["cancel"] = True
|
||
return
|
||
# 蓄满:施加效果
|
||
effectComp = compFactory.CreateEffect(playerId)
|
||
if itemName == PLASTER:
|
||
effectComp.AddEffectToEntity("regeneration", 5, 0, False)
|
||
elif itemName == SPLINT:
|
||
effectComp.AddEffectToEntity("resistance", 10, 0, False)
|
||
elif itemName == ALCOHOL_WIPES:
|
||
effectComp.RemoveEffectFromEntity("poison")
|
||
# 消耗 1 个
|
||
self._ConsumeOne(playerId)
|
||
args["changeItem"] = True
|
||
|
||
def _ConsumeOne(self, playerId):
|
||
itemComp = compFactory.CreateItem(playerId)
|
||
slotId = itemComp.GetSelectSlotId()
|
||
itemDict = itemComp.GetPlayerItem(serverApi.GetMinecraftEnum().ItemPosType.INVENTORY, slotId, True)
|
||
if not itemDict:
|
||
return
|
||
count = itemDict.get("count", 1)
|
||
itemComp.SetInvItemNum(slotId, count - 1)
|
||
|
||
# ---------- 血袋 / 空血袋 ----------
|
||
def OnEatFood(self, args):
|
||
playerId = args.get("playerId")
|
||
itemName = (args.get("itemDict") or {}).get("itemName")
|
||
if not playerId:
|
||
return
|
||
if itemName == BLOOD_BAG:
|
||
self._AddHealth(playerId, HEAL_AMOUNT)
|
||
elif itemName == BLOOD_BAG_EMPTY:
|
||
for i in range(1, DONATE_TOTAL + 1):
|
||
self.AddTimer(DONATE_INTERVAL * i, self._AddHealth, playerId, -DONATE_STEP)
|
||
self.AddTimer(DONATE_INTERVAL * (DONATE_TOTAL + 1), self._GiveBloodBag, playerId)
|
||
|
||
def _AddHealth(self, playerId, delta):
|
||
attrType = serverApi.GetMinecraftEnum().AttrType.HEALTH
|
||
attrComp = compFactory.CreateAttr(playerId)
|
||
cur = attrComp.GetAttrValue(attrType)
|
||
limit = attrComp.GetAttrMaxValue(attrType)
|
||
attrComp.SetAttrValue(attrType, max(0.0, min(cur + delta, limit)))
|
||
|
||
def _GiveBloodBag(self, playerId):
|
||
itemDict = {"itemName": BLOOD_BAG, "count": 1, "auxValue": 0}
|
||
compFactory.CreateItem(playerId).SpawnItemToPlayerInv(itemDict, playerId, -1) |