def __init__(self,leader,remoteLeaderName=None): self.leader = leader self.members = [leader] self.invites = [] self.world = leader.world if not remoteLeaderName: self.remoteLeaderName = self.leader.publicName if self.world.daemonPerspective: info = Alliance.masterAllianceInfo[self.remoteLeaderName] = [(leader.publicName,leader.party.members[0].name)] self.world.daemonPerspective.callRemote("setAllianceInfo",leader.publicName,info) else: self.remoteLeaderName = remoteLeaderName self.allianceInfo = AllianceInfo(self) self.setupForPlayer(leader) self.tick()
class Alliance: #leaders->[(pname,cname)] masterAllianceInfo = {} def __init__(self,leader,remoteLeaderName=None): self.leader = leader self.members = [leader] self.invites = [] self.world = leader.world if not remoteLeaderName: self.remoteLeaderName = self.leader.publicName if self.world.daemonPerspective: info = Alliance.masterAllianceInfo[self.remoteLeaderName] = [(leader.publicName,leader.party.members[0].name)] self.world.daemonPerspective.callRemote("setAllianceInfo",leader.publicName,info) else: self.remoteLeaderName = remoteLeaderName self.allianceInfo = AllianceInfo(self) self.setupForPlayer(leader) self.tick() def setupForPlayer(self,player): player.alliance = self player.mind.callRemote("setAllianceInfo",self.allianceInfo) player.mind.callRemote("setAllianceInvite",None) def giveMoney(self,source,worth): if not len(self.members): print "WARNING: Alliance with no members in giveMoney" return rewards = [] for m in self.members: if m == source: rewards.append(m) continue if m.zone != source.zone: continue if GetRange(m.party.members[0].mob,source.party.members[0].mob) > 50: continue rewards.append(m) num = len(rewards) if worth < num: worth = num if num <1: return worth /= num wtext = GenMoneyText(worth) for m in rewards: m.giveMoney(worth) m.mind.callRemote("playSound",SND_COINS) if num > 1: m.sendGameText(RPG_MSG_GAME_GAINED,"Your share of the wealth is: %s\\n"%wtext) else: m.sendGameText(RPG_MSG_GAME_GAINED,"You plunder %s from the corpse.\\n"%wtext) def rewardXP(self,source,totalXP,isKill=False,best=1): count = 0 if not len(self.members): print "WARNING: Alliance with no members in rewardXP" return rewards = [] for m in self.members: if m == source: rewards.append(m) continue if m.zone != source.zone: continue if GetRange(m.party.members[0].mob,source.party.members[0].mob) > 50: continue rewards.append(m) num = len(rewards) if isKill and num == 1 and len(rewards[0].party.members) == 1: totalXP*=1.33 if num < 1: return memberXP = int(math.ceil(float(totalXP) / float(num))) memberXP *= XPBONUS[num-1] if not isKill: best = 1 for m in rewards: m.rewardXP(memberXP,best) def rewardFaction(self,source,faction,amount): count = 0 if not len(self.members): print "WARNING: Alliance with no members in rewardFaction" return rewards = [] for m in self.members: if m == source: rewards.append(m) continue if m.zone != source.zone: continue if GetRange(m.party.members[0].mob,source.party.members[0].mob) > 50: continue rewards.append(m) num = len(rewards) if num < 1: return memberFaction = int(math.ceil(float(amount)/float(num))) #memberFaction*=XPBONUS[num] for m in rewards: m.rewardFaction(faction,memberFaction) def rewardKillFaction(self,killer,mob): factions = list(mob.spawn.factions) if not len(factions): return if not len(self.members): print "WARNING: Alliance with no members in rewardKillFaction" return totalFaction = float(mob.plevel*3) #decrease factions for f in factions: self.rewardFaction(killer,f,-totalFaction) for kf in mob.spawn.killFactions: if kf.percent < 0: kfaction = math.ceil((totalFaction/2.0)*kf.percent) #easier to lose faction else: kfaction = math.ceil((totalFaction/4.0)*kf.percent) #harder to gain self.rewardFaction(killer,kf.faction,kfaction) #this shouldn't be automatic #increase/decease related factions #for r in list(f.relations): # if r.relation < 0: # # if r.relation > 0: # self.rewardFaction(killer,r.otherFaction,-math.ceil(float(totalFaction)/2.0)) # Penalize the killing of other players with # too low relative level. def killPenalty(self,killer,mob): if not len(self.members): print "WARNING: Alliance with no members in killPenalty" return # Set up kill penalty message according to realm. if mob.realm == RPG_REALM_LIGHT: msg = "transgressed against the gods of light!" elif mob.realm == RPG_REALM_DARKNESS: msg = "transgressed against the gods of darkness!" else: msg = "displeased the earthbound!" # Get the name of the killer. Replace spaces with # underscores to get internal name. killerName = killer.charName skillerName = killerName.replace(' ','_') # All alliance members must know. for player in self.members: # If this is the killer, every character in the killers party # loses a good amount of experience, depending on his level # to accomodate for any exponential increases in strength and # experience. if killer == player: player.sendGameText(RPG_MSG_GAME_YELLOW,r'You have %s\n'%(msg)) for character in player.party.members: character.loseXP(1.5*float(character.spawn.plevel),False) # Else notify the other members of the killers transgression. else: player.sendGameText(RPG_MSG_GAME_YELLOW,r'<a:gamelinkcharlink%s>%s</a> has %s\n'%(skillerName,killerName,msg)) def rewardKillXP(self,killer,mob): #todo alliances if not len(self.members): print "WARNING: Alliance with no members in rewardKillXp" return best = 1 try: for m in self.members: if len(self.members) > 1 and m.role.name == "Immortal": continue for char in m.party.members: if char.mob.plevel > best and not char.dead: best = char.mob.plevel except: traceback.print_exc() print "Warning: Exception in getting best alliance member for rewardKillXP" best = mob.plevel if mob.player: if not mob.playerInitiate[killer][0] and best - mob.plevel > 10: #penalty! self.killPenalty(killer,mob) return False #no XP for player vs player kills right now if mob.player: return True adjust = float(mob.plevel - best) if adjust < -10: return False#no XP for mobs < 10 levels if adjust < 0: adjust /= 5.0 if adjust > 10.0: adjust = 10.0 totalXP = mob.plevel*12.5 if mob.slevel: totalXP += mob.slevel*6.5 if mob.tlevel: totalXP += mob.tlevel*2.5 totalXP *= mob.xpMod totalXP += totalXP totalXP *= killer.zone.xpMod totalXP += totalXP*(mob.plevel/10) if mob.spawn.difficultyMod > 1.0 or mob.spawn.damageMod > 1.0 or mob.spawn.healthMod > 1.0: # determine which modifier is the greatest value xpModifier = 1.0 if mob.spawn.difficultyMod > xpModifier: xpModifier = mob.spawn.difficultyMod if mob.spawn.damageMod > xpModifier: xpModifier = mob.spawn.damageMod if mob.spawn.healthMod > xpModifier: xpModifier = mob.spawn.healthMod # modify the totalXP by the greatest modifier totalXP += totalXP * (xpModifier * 3) elif mob.spawn.flags&RPG_SPAWN_UNIQUE: totalXP += totalXP * (.5) totalXP /= 100.0 if mob.slevel and mob.tlevel: totalXP = int(math.ceil(totalXP+mob.plevel*4.0+mob.slevel*2+mob.tlevel)*1.2)+35 elif mob.slevel: totalXP = int(math.ceil(totalXP+mob.plevel*4.0+mob.slevel*2)*1.2)+35 else: totalXP = int(math.ceil(totalXP+mob.plevel*4.0)*1.2)+35 totalXP += totalXP*(adjust*.25) self.rewardXP(killer,totalXP,True,best) return True def lootMessage(self,sender, lootitem): senderName = sender.charName ssenderName = senderName.replace(' ','_') for m in self.members: if sender == m: m.sendGameText(RPG_MSG_GAME_YELLOW,r'You have looted: <a:Item%s>%s</a>\n'%(GetTWikiName(lootitem.itemProto.name),lootitem.name)) else: m.sendGameText(RPG_MSG_GAME_YELLOW,r'<a:gamelinkcharlink%s>%s</a> has looted: <a:Item%s>%s</a>\n'%(ssenderName,senderName,GetTWikiName(lootitem.itemProto.name),lootitem.name)) def message(self, sender, msg): # Get the senders character name, with and without chat pseudo formatting. name = sender.charName sname = name.replace(' ','_') # Assemble the message. msg = r'Alliance: <<a:gamelinkcharlink%s>%s</a>> %s\n'%(sname,name,msg) # If this server uses multiple clusters, check if there are alliance # members in a different cluster. if self.world.daemonPerspective: # More members in alliance than current instance means members # in other clusters. if self.countMembers() > len(self.members): # Inform the members in other clusters. self.world.daemonPerspective.callRemote("propagateCmd","sendAllianceMsg",name,msg,self.remoteLeaderName) # Run through all members in the current cluster and send them the message. for m in self.members: m.sendSpeechText(RPG_MSG_SPEECH_ALLIANCE,msg,name) def kick(self,name): if self.remoteLeaderName != self.leader.publicName: return who = None for m in self.members: if m.party.members[0].name.lower() == name.lower(): who = m break if self.world.daemonPerspective: a = Alliance.masterAllianceInfo[self.remoteLeaderName] info = [(pname,cname) for pname,cname in a if pname != name] if info != a: self.world.daemonPerspective.callRemote("setAllianceInfo",self.remoteLeaderName,info) if who: if who == self.leader: return leaderName = self.leader.charName sleaderName = leaderName.replace(' ','_') who.sendGameText(RPG_MSG_GAME_GOOD,"You have been removed from <a:gamelinkcharlink%s>%s</a>'s alliance.\\n"%(sleaderName,leaderName)) self.leave(who) def invite(self,who): if self.remoteLeaderName != self.leader.publicName: return who.invite = Invite(who,self.leader) self.invites.append(who.invite) who.mind.callRemote("setAllianceInvite",self.remoteLeaderName) def disband(self): if not self.leader: print "WARNING: Alliance disbanded with no leader!" return output = self.leader.publicName == self.remoteLeaderName self.cancelInvites() leader = self.leader self.leader = None leaderName = leader.charName sleaderName = leaderName.replace(' ','_') for m in self.members: if not m.loggingOut and not m.transfering: m.alliance = Alliance(m) if m == leader and output: m.sendGameText(RPG_MSG_GAME_GOOD,"Your alliance has been disbanded.\\n") elif output: m.sendGameText(RPG_MSG_GAME_GOOD,"<a:gamelinkcharlink%s>%s</a>'s alliance has been disbanded.\\n"%(sleaderName,leaderName)) else: m.alliance = None self.members = [] #make sure this is never called for the leader, they must disband def leave(self,who): if not who.transfering and who.publicName == self.remoteLeaderName: self.disband() return if len(self.members) == 1: #we are a remote alliance self.disband() if not who.transfering: try: who.sendGameText(RPG_MSG_GAME_GOOD,"You have left the alliance.\\n") except: pass return if self.leader == who: members = self.members[:] members.remove(self.leader) self.members = [self.leader] alliance = Alliance(members[0],self.remoteLeaderName) members.pop(0) for k in members: alliance.setupForPlayer(k) alliance.allianceInfo.refresh() self.disband() if not who.transfering: try: who.sendGameText(RPG_MSG_GAME_GOOD,"You have left the alliance.\\n") except: pass return nmembers = [] for m in self.members: if m == who: if not m.loggingOut and not m.transfering: try: m.sendGameText(RPG_MSG_GAME_GOOD,"You have left the alliance.\\n") except: pass continue else: m.alliance = None else: nmembers.append(m) try: if not who.transfering: if self.world.daemonPerspective: #make sure local info is accurate a = Alliance.masterAllianceInfo[self.remoteLeaderName] na = [(pname,cname) for pname,cname in a if pname != who.publicName] Alliance.masterAllianceInfo[self.remoteLeaderName] = na self.world.daemonPerspective.callRemote("clearAllianceInfo",who.publicName) except: traceback.print_exc() self.members = nmembers #the person who left is still in the observer list self.allianceInfo.refresh() #we do this here so we overwrite the refreshed data for the individual who left if not who.loggingOut and not who.transfering: who.alliance = Alliance(who) leaveName = who.charName sleaveName = leaveName.replace(' ','_') if not who.transfering: for m in self.members: try: m.sendGameText(RPG_MSG_GAME_GOOD,"<a:gamelinkcharlink%s>%s</a> has left the alliance.\\n"%(sleaveName,leaveName)) except: pass def tick(self): if not self.leader: #make sure to none out leader!!! return if not len(self.members): print "WARNING: 0 member alliance" return if self.world.daemonPerspective: #filter members try: a = Alliance.masterAllianceInfo[self.remoteLeaderName] except KeyError: self.disband() return remove = [] keep = [] for m in self.members[:]: found = False for pname,cname in a: if pname == m.publicName: found = True break if not found: remove.append(m) else: keep.append(m) if self.leader in remove: if len(keep): alliance = Alliance(keep[0],self.remoteLeaderName) self.members.remove(keep[0]) keep.pop(0) for k in keep: self.members.remove(k) alliance.setupForPlayer(k) alliance.allianceInfo.refresh() for m in remove: self.members.remove(m) a = Alliance(m) a.setupForPlayer(m) if not len(self.members): return try: if True:#len(self.members) > 1: self.allianceInfo.refresh() except: traceback.print_exc() reactor.callLater(2,self.tick) def cancelInvite(self,who): if not who.invite: return ninvites = [] for inv in self.invites: if inv.invited == who: who.invite = None continue ninvites.append(inv) self.invites = ninvites def cancelInvites(self): invites = copy(self.invites) for inv in invites: self.cancelInvite(inv.invited) def countMembers(self): num = len(self.members) if self.world.daemonPerspective: a = Alliance.masterAllianceInfo[self.remoteLeaderName] for pname,cname in a: found = False for m in self.members: if m.publicName == pname: found = True break if not found: num += 1 return num def join(self,who): found = False if self.countMembers() >= 6: self.cancelInvite(who) return False if len(who.alliance.members) > 1: self.cancelInvite(who) return False for inv in self.invites: if inv.invited == who: found = True break if not found: who.invite = None return False if self.world.daemonPerspective: self.world.daemonPerspective.callRemote("joinAlliance",self.remoteLeaderName,who.publicName,who.party.members[0].name) a = Alliance.masterAllianceInfo[self.remoteLeaderName] a.append((who.publicName,who.party.members[0])) self.members.append(who) if who.alliance.leader == who: who.alliance.leader = None who.alliance = self who.mind.callRemote("setAllianceInfo",self.allianceInfo) #self.allianceInfo.refresh() self.cancelInvite(who) return True