# -*- 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)