async def bleedout(cmd): user_data = EwUser(member=cmd.message.author) mutations = user_data.get_mutations() if ewcfg.mutation_id_bleedingheart not in mutations: response = "You don't have an open enough wound to just gush your blood everywhere." elif user_data.bleed_storage == 0: response = "There's nothing to bleed. Sounds like someone has a persecution complex..." elif user_data.bleed_storage > user_data.slimes: #don't think this is possible, but just in case response = "Wait, wouldn't that kill you? Better not." else: response = "You clutch your malformed heart and squeeze as hard as you can. The intense pain makes you fall to your knees, and your slime drops in spurts to the floor under you as you gasp desperately for relief. You have been bled dry." poi = ewcfg.id_to_poi.get(user_data.poi) district_data = EwDistrict(id_server=cmd.message.guild.id, district=poi.id_poi) user_data.change_slimes(n=-user_data.bleed_storage, source=ewcfg.source_bleeding) district_data.change_slimes(n=user_data.bleed_storage, source=ewcfg.source_bleeding) user_data.bleed_storage = 0 user_data.persist() district_data.persist() return await ewutils.send_message( cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, response))
async def bleedSlimes(id_server = None): if id_server != None: try: client = get_client() server = client.get_server(id_server) conn_info = databaseConnect() conn = conn_info.get('conn') cursor = conn.cursor(); cursor.execute("SELECT id_user FROM users WHERE id_server = %s AND {bleed_storage} > 1".format( bleed_storage = ewcfg.col_bleed_storage ), ( id_server, )) users = cursor.fetchall() total_bled = 0 deathreport = "" resp_cont = EwResponseContainer(id_server = id_server) for user in users: user_data = EwUser(id_user = user[0], id_server = id_server) slimes_to_bleed = user_data.bleed_storage * (1 - .5 ** (ewcfg.bleed_tick_length / ewcfg.bleed_half_life)) slimes_to_bleed = max(slimes_to_bleed, ewcfg.bleed_tick_length * 1000) slimes_to_bleed = min(slimes_to_bleed, user_data.bleed_storage) slimes_dropped = user_data.totaldamage + user_data.slimes district_data = EwDistrict(id_server = id_server, district = user_data.poi) #round up or down, randomly weighted remainder = slimes_to_bleed - int(slimes_to_bleed) if random.random() < remainder: slimes_to_bleed += 1 slimes_to_bleed = int(slimes_to_bleed) if slimes_to_bleed >= 1: user_data.bleed_storage -= slimes_to_bleed user_data.change_slimes(n = - slimes_to_bleed, source = ewcfg.source_bleeding) if user_data.slimes < 0: user_data.die(cause = ewcfg.cause_bleeding) #user_data.change_slimes(n = -slimes_dropped / 10, source = ewcfg.source_ghostification) player_data = EwPlayer(id_server = user_data.id_server, id_user = user_data.id_user) deathreport = "{skull} *{uname}*: You have succumbed to your wounds. {skull}".format(skull = ewcfg.emote_slimeskull, uname = player_data.display_name) resp_cont.add_channel_response(ewcfg.channel_sewers, deathreport) user_data.persist() district_data.change_slimes(n = slimes_to_bleed, source = ewcfg.source_bleeding) district_data.persist() total_bled += slimes_to_bleed await ewrolemgr.updateRoles(client = client, member = server.get_member(user_data.id_user)) await resp_cont.post() conn.commit() finally: # Clean up the database handles. cursor.close() databaseClose(conn_info)
async def enemyBleedSlimes(id_server = None): if id_server != None: try: conn_info = databaseConnect() conn = conn_info.get('conn') cursor = conn.cursor(); cursor.execute("SELECT id_enemy FROM enemies WHERE id_server = %s AND {bleed_storage} > 1".format( bleed_storage = ewcfg.col_enemy_bleed_storage ), ( id_server, )) enemies = cursor.fetchall() total_bled = 0 resp_cont = EwResponseContainer(id_server = id_server) for enemy in enemies: enemy_data = EwEnemy(id_enemy = enemy[0], id_server = id_server) slimes_to_bleed = enemy_data.bleed_storage * (1 - .5 ** (ewcfg.bleed_tick_length / ewcfg.bleed_half_life)) slimes_to_bleed = max(slimes_to_bleed, ewcfg.bleed_tick_length * 1000) slimes_to_bleed = min(slimes_to_bleed, enemy_data.bleed_storage) district_data = EwDistrict(id_server = id_server, district = enemy_data.poi) #round up or down, randomly weighted remainder = slimes_to_bleed - int(slimes_to_bleed) if random.random() < remainder: slimes_to_bleed += 1 slimes_to_bleed = int(slimes_to_bleed) if slimes_to_bleed >= 1: enemy_data.bleed_storage -= slimes_to_bleed enemy_data.change_slimes(n = - slimes_to_bleed, source = ewcfg.source_bleeding) enemy_data.persist() district_data.change_slimes(n = slimes_to_bleed, source = ewcfg.source_bleeding) district_data.persist() total_bled += slimes_to_bleed if enemy_data.slimes <= 0: ewhunting.delete_enemy(enemy_data) await resp_cont.post() conn.commit() finally: # Clean up the database handles. cursor.close() databaseClose(conn_info)
async def revive(cmd): time_now = int(time.time()) response = "" if cmd.message.channel.name != ewcfg.channel_endlesswar and cmd.message.channel.name != ewcfg.channel_sewers: response = "Come to me. I hunger. #{}.".format(ewcfg.channel_sewers) else: player_data = EwUser(member=cmd.message.author) time_until_revive = (player_data.time_lastdeath + player_data.degradation) - time_now if time_until_revive > 0: response = "ENDLESS WAR is not ready to {} you yet ({}s).".format( cmd.tokens[0], time_until_revive) return await ewutils.send_message( cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, response)) slimeoid = EwSlimeoid(member=cmd.message.author) if player_data.life_state == ewcfg.life_state_corpse: market_data = EwMarket(id_server=cmd.message.server.id) # Endless War collects his fee. #fee = (player_data.slimecoin / 10) #player_data.change_slimecoin(n = -fee, coinsource = ewcfg.coinsource_revival) #market_data.slimes_revivefee += fee #player_data.busted = False # Preserve negaslime if player_data.slimes < 0: #market_data.negaslime += player_data.slimes player_data.change_slimes(n=-player_data.slimes) # set to 0 # reset slimelevel to zero player_data.slimelevel = 0 # Set time of last revive. This used to provied spawn protection, but currently isn't used. player_data.time_lastrevive = time_now if player_data.degradation >= 100: player_data.life_state = ewcfg.life_state_shambler player_data.change_slimes(n=0.5 * ewcfg.slimes_shambler) player_data.trauma = "" poi_death = ewcfg.id_to_poi.get(player_data.poi_death) if ewmap.inaccessible(poi=poi_death, user_data=player_data): player_data.poi = ewcfg.poi_id_downtown else: player_data.poi = poi_death.id_poi else: # Set life state. This is what determines whether the player is actually alive. player_data.life_state = ewcfg.life_state_juvenile # Give player some initial slimes. player_data.change_slimes(n=ewcfg.slimes_onrevive) # Get the player out of the sewers. player_data.poi = ewcfg.poi_id_downtown player_data.persist() market_data.persist() # Shower every district in the city with slime from the sewers. sewer_data = EwDistrict(district=ewcfg.poi_id_thesewers, id_server=cmd.message.server.id) # the amount of slime showered is divided equally amongst the districts districts_amount = len(ewcfg.capturable_districts) geyser_amount = int(0.5 * sewer_data.slimes / districts_amount) # Get a list of all the districts for poi in ewcfg.capturable_districts: district_data = EwDistrict(district=poi, id_server=cmd.message.server.id) district_data.change_slimes(n=geyser_amount) sewer_data.change_slimes(n=-1 * geyser_amount) district_data.persist() sewer_data.persist() sewer_inv = ewitem.inventory(id_user=sewer_data.name, id_server=sewer_data.id_server) for item in sewer_inv: district = ewcfg.poi_id_slimesea if random.random() < 0.5: district = random.choice(ewcfg.capturable_districts) ewitem.give_item(id_item=item.get("id_item"), id_user=district, id_server=sewer_data.id_server) await ewrolemgr.updateRoles(client=cmd.client, member=cmd.message.author) response = '{slime4} Geysers of fresh slime erupt from every manhole in the city, showering their surrounding districts. {slime4} {name} has been reborn in slime. {slime4}'.format( slime4=ewcfg.emote_slime4, name=cmd.message.author.display_name) else: response = 'You\'re not dead just yet.' # deathreport = "You were {} by {}. {}".format(kill_descriptor, cmd.message.author.display_name, ewcfg.emote_slimeskull) # deathreport = "{} ".format(ewcfg.emote_slimeskull) + ewutils.formatMessage(member, deathreport) if slimeoid.life_state == ewcfg.slimeoid_state_active: reunite = "" brain = ewcfg.brain_map.get(slimeoid.ai) reunite += brain.str_revive.format(slimeoid_name=slimeoid.name) new_poi = ewcfg.id_to_poi.get(player_data.poi) revivechannel = ewutils.get_channel(cmd.message.server, new_poi.channel) reunite = ewutils.formatMessage(cmd.message.author, reunite) await ewutils.send_message(cmd.client, revivechannel, reunite) # Send the response to the player. await ewutils.send_message( cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, response))
def decaySlimes(id_server = None): if id_server != None: try: conn_info = databaseConnect() conn = conn_info.get('conn') cursor = conn.cursor(); cursor.execute("SELECT id_user FROM users WHERE id_server = %s AND {slimes} > 1".format( slimes = ewcfg.col_slimes ), ( id_server, )) users = cursor.fetchall() total_decayed = 0 for user in users: user_data = EwUser(id_user = user[0], id_server = id_server) slimes_to_decay = user_data.slimes - (user_data.slimes * (.5 ** (ewcfg.update_market / ewcfg.slime_half_life))) #round up or down, randomly weighted remainder = slimes_to_decay - int(slimes_to_decay) if random.random() < remainder: slimes_to_decay += 1 slimes_to_decay = int(slimes_to_decay) if slimes_to_decay >= 1: user_data.change_slimes(n = -slimes_to_decay, source = ewcfg.source_decay) user_data.persist() total_decayed += slimes_to_decay cursor.execute("SELECT district FROM districts WHERE id_server = %s AND {slimes} > 1".format( slimes = ewcfg.col_district_slimes ), ( id_server, )) districts = cursor.fetchall() for district in districts: district_data = EwDistrict(district = district[0], id_server = id_server) slimes_to_decay = district_data.slimes - (district_data.slimes * (.5 ** (ewcfg.update_market / ewcfg.slime_half_life))) #round up or down, randomly weighted remainder = slimes_to_decay - int(slimes_to_decay) if random.random() < remainder: slimes_to_decay += 1 slimes_to_decay = int(slimes_to_decay) if slimes_to_decay >= 1: district_data.change_slimes(n = -slimes_to_decay, source = ewcfg.source_decay) district_data.persist() total_decayed += slimes_to_decay cursor.execute("UPDATE markets SET {decayed} = ({decayed} + %s) WHERE {server} = %s".format( decayed = ewcfg.col_decayed_slimes, server = ewcfg.col_id_server ), ( total_decayed, id_server )) conn.commit() finally: # Clean up the database handles. cursor.close() databaseClose(conn_info)
async def scavenge(cmd): market_data = EwMarket(id_server=cmd.message.author.server.id) user_data = EwUser(member=cmd.message.author) mutations = user_data.get_mutations() time_now = int(time.time()) response = "" time_since_last_scavenge = time_now - user_data.time_lastscavenge # Kingpins can't scavenge. if user_data.life_state == ewcfg.life_state_kingpin or user_data.life_state == ewcfg.life_state_grandfoe: return # ghosts cant scavenge if user_data.life_state == ewcfg.life_state_corpse: return await ewutils.send_message( cmd.client, cmd.message.channel, ewutils.formatMessage( cmd.message.author, "What would you want to do that for? You're a ghost, you have no need for such lowly materialistic possessions like slime. You only engage in intellectual pursuits now. {} if you want to give into your base human desire to see numbers go up." .format(ewcfg.cmd_revive))) # currently not active - no cooldown if time_since_last_scavenge < ewcfg.cd_scavenge: return await ewutils.send_message( cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, "Slow down, you filthy hyena.")) # Scavenge only in location channels if ewmap.channel_name_is_poi(cmd.message.channel.name) == True: if user_data.hunger >= user_data.get_hunger_max(): return await ewutils.send_message( cmd.client, cmd.message.channel, ewutils.formatMessage( cmd.message.author, "You are too exhausted to scrounge up scraps of slime off the street! Go get some grub!" )) else: district_data = EwDistrict(district=user_data.poi, id_server=cmd.message.author.server.id) user_initial_level = user_data.slimelevel # add scavenged slime to user if ewcfg.mutation_id_trashmouth in mutations: time_since_last_scavenge *= 3 time_since_last_scavenge = min(max(1, time_since_last_scavenge), 30) scavenge_mod = 0.003 * (time_since_last_scavenge**0.9) if ewcfg.mutation_id_whitenationalist in mutations and market_data.weather == "snow": scavenge_mod *= 1.5 if ewcfg.mutation_id_webbedfeet in mutations: district_slimelevel = len(str(district_data.slimes)) scavenge_mod *= max(1, min(district_slimelevel - 3, 4)) scavenge_yield = math.floor(scavenge_mod * district_data.slimes) levelup_response = user_data.change_slimes( n=scavenge_yield, source=ewcfg.source_scavenging) district_data.change_slimes(n=-1 * scavenge_yield, source=ewcfg.source_scavenging) district_data.persist() if levelup_response != "": response += levelup_response + "\n\n" #response += "You scrape together {} slime from the streets.\n\n".format(scavenge_yield) if cmd.tokens_count > 1: item_search = ewutils.flattenTokenListToString(cmd.tokens[1:]) loot_resp = ewitem.item_lootspecific( id_server=user_data.id_server, id_user=user_data.id_user, item_search=item_search) response += loot_resp else: loot_multiplier = 1.0 + ewitem.get_inventory_size( owner=user_data.poi, id_server=user_data.id_server) loot_chance = loot_multiplier / ewcfg.scavenge_item_rarity if ewcfg.mutation_id_dumpsterdiver in mutations: loot_chance *= 10 if random.random() < loot_chance: loot_resp = ewitem.item_lootrandom( id_server=user_data.id_server, id_user=user_data.id_user) response += loot_resp # Fatigue the scavenger. hunger_cost_mod = ewutils.hunger_cost_mod(user_data.slimelevel) extra = hunger_cost_mod - int( hunger_cost_mod ) # extra is the fractional part of hunger_cost_mod user_data.hunger += ewcfg.hunger_perscavenge * int(hunger_cost_mod) if extra > 0: # if hunger_cost_mod is not an integer # there's an x% chance that an extra stamina is deducted, where x is the fractional part of hunger_cost_mod in percent (times 100) if random.randint(1, 100) <= extra * 100: user_data.hunger += ewcfg.hunger_perscavenge user_data.time_lastscavenge = time_now user_data.persist() if not response == "": await ewutils.send_message( cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, response)) else: return await ewutils.send_message( cmd.client, cmd.message.channel, ewutils.formatMessage( cmd.message.author, "You'll find no slime here, this place has been picked clean. Head into the city to try and scavenge some slime." ))
async def disembark(cmd): # can only use movement commands in location channels if ewutils.channel_name_is_poi(cmd.message.channel.name) == False: return await ewutils.send_message(cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, "You must {} in a zone's channel.".format(cmd.tokens[0]))) user_data = EwUser(member = cmd.message.author) response = "" resp_cont = ewutils.EwResponseContainer(client = cmd.client, id_server = user_data.id_server) # prevent ghosts currently inhabiting other players from moving on their own if user_data.get_inhabitee(): response = "You might want to **{}** of the poor soul you've been tormenting first.".format(ewcfg.cmd_letgo) return await ewutils.send_message(cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, response)) # can only disembark when you're on a transport vehicle elif user_data.poi in ewcfg.transports: transport_data = EwTransport(id_server = user_data.id_server, poi = user_data.poi) response = "{}ing.".format(cmd.tokens[0][1:].lower()).capitalize() stop_poi = ewcfg.id_to_poi.get(transport_data.current_stop) # if stop_poi.is_subzone: # stop_poi = ewcfg.id_to_poi.get(stop_poi.mother_district) if ewmap.inaccessible(user_data = user_data, poi = stop_poi): return await ewutils.send_message(cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, "You're not allowed to go there (bitch).")) # schedule tasks for concurrent execution message_task = asyncio.ensure_future(ewutils.send_message(cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, response))) wait_task = asyncio.ensure_future(asyncio.sleep(5)) # Take control of the move for this player. ewmap.move_counter += 1 move_current = ewutils.moves_active[cmd.message.author.id] = ewmap.move_counter await message_task await wait_task # check if the user entered another movement command while waiting for the current one to be completed if move_current != ewutils.moves_active[cmd.message.author.id]: return user_data = EwUser(member = cmd.message.author) transport_data = EwTransport(id_server = user_data.id_server, poi = transport_data.poi) # cancel move, if the user has left the transport while waiting for movement to be completed (e.g. by dying) if user_data.poi != transport_data.poi: return stop_poi = ewcfg.id_to_poi.get(transport_data.current_stop) # juvies can't swim if transport_data.current_stop == ewcfg.poi_id_slimesea and user_data.life_state != ewcfg.life_state_corpse: if user_data.life_state == ewcfg.life_state_kingpin: response = "You try to heave yourself over the railing as you're hit by a sudden case of sea sickness. You puke into the sea and sink back on deck." response = ewutils.formatMessage(cmd.message.author, response) return await ewutils.send_message(cmd.client, cmd.message.channel, response) user_data.poi = ewcfg.poi_id_slimesea user_data.trauma = ewcfg.trauma_id_environment die_resp = user_data.die(cause = ewcfg.cause_drowning) user_data.persist() resp_cont.add_response_container(die_resp) response = "{} jumps over the railing of the ferry and promptly drowns in the slime sea.".format(cmd.message.author.display_name) resp_cont.add_channel_response(channel = ewcfg.channel_slimesea, response = response) resp_cont.add_channel_response(channel = ewcfg.channel_ferry, response = response) await ewrolemgr.updateRoles(client = cmd.client, member = cmd.message.author) # they also can't fly elif transport_data.transport_type == ewcfg.transport_type_blimp and not stop_poi.is_transport_stop and user_data.life_state != ewcfg.life_state_corpse: user_mutations = user_data.get_mutations() if user_data.life_state == ewcfg.life_state_kingpin: response = "Your life flashes before your eyes, as you plummet towards your certain death. A lifetime spent being a piece of shit and playing videogames all day. You close your eyes and... BOING! You open your eyes again to see a crew of workers transporting the trampoline that broke your fall. You get up and dust yourself off, sighing heavily." response = ewutils.formatMessage(cmd.message.author, response) resp_cont.add_channel_response(channel = stop_poi.channel, response = response) user_data.poi = stop_poi.id_poi user_data.persist() await ewrolemgr.updateRoles(client = cmd.client, member = cmd.message.author) return await resp_cont.post() elif ewcfg.mutation_id_lightasafeather in user_mutations: response = "With a running jump you launch yourself out of the blimp and begin falling to your soon-to-be demise... but then a strong updraft breaks your fall and you land unscathed. " response = ewutils.formatMessage(cmd.message.author, response) resp_cont.add_channel_response(channel = stop_poi.channel, response = response) user_data.poi = stop_poi.id_poi user_data.persist() await user_data.move_inhabitants(id_poi = stop_poi.id_poi) await ewrolemgr.updateRoles(client = cmd.client, member = cmd.message.author) return await resp_cont.post() district_data = EwDistrict(id_server = user_data.id_server, district = stop_poi.id_poi) district_data.change_slimes(n = user_data.slimes) district_data.persist() user_data.poi = stop_poi.id_poi user_data.trauma = ewcfg.trauma_id_environment die_resp = user_data.die(cause = ewcfg.cause_falling) user_data.persist() resp_cont.add_response_container(die_resp) response = "SPLAT! A body collides with the asphalt with such force, that it is utterly annihilated, covering bystanders in blood and slime and guts." resp_cont.add_channel_response(channel = stop_poi.channel, response = response) await ewrolemgr.updateRoles(client = cmd.client, member = cmd.message.author) # update user location, if move successful else: # if stop_poi.is_subzone: # stop_poi = ewcfg.id_to_poi.get(stop_poi.mother_district) if ewmap.inaccessible(user_data = user_data, poi = stop_poi): return await ewutils.send_message(cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, "You're not allowed to go there (bitch).")) user_data.poi = stop_poi.id_poi user_data.persist() await user_data.move_inhabitants(id_poi = stop_poi.id_poi) response = "You enter {}".format(stop_poi.str_name) await ewrolemgr.updateRoles(client = cmd.client, member = cmd.message.author) await ewutils.send_message(cmd.client, ewutils.get_channel(cmd.guild, stop_poi.channel), ewutils.formatMessage(cmd.message.author, response)) # SWILLDERMUK await ewutils.activate_trap_items(stop_poi.id_poi, user_data.id_server, user_data.id_user) return return await resp_cont.post() else: response = "You are not currently riding any transport." return await ewutils.send_message(cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, response))
async def weather_tick(id_server=None): if id_server != None: try: market_data = EwMarket(id_server=id_server) if market_data.weather == ewcfg.weather_sunny: exposed_pois = [] exposed_pois.extend(ewcfg.capturable_districts) exposed_pois.extend(ewcfg.outskirts) exposed_pois = tuple(exposed_pois) users = ewutils.execute_sql_query( "SELECT id_user FROM users WHERE id_server = %s AND {poi} IN %s AND {life_state} > 0" .format(poi=ewcfg.col_poi, life_state=ewcfg.col_life_state), (id_server, exposed_pois)) for user in users: try: user_data = EwUser(id_user=user[0], id_server=id_server) if user_data.life_state == ewcfg.life_state_kingpin: continue else: mutations = user_data.get_mutations() if ewcfg.mutation_id_airlock in mutations: user_data.hunger -= min(user_data.hunger, 5) except: ewutils.logMsg( "Error occurred in weather tick for server {}". format(id_server)) if market_data.weather != ewcfg.weather_bicarbonaterain: return exposed_pois = [] exposed_pois.extend(ewcfg.capturable_districts) exposed_pois.extend(ewcfg.outskirts) exposed_pois = tuple(exposed_pois) client = ewutils.get_client() server = client.get_guild(id_server) users = ewutils.execute_sql_query( "SELECT id_user FROM users WHERE id_server = %s AND {poi} IN %s AND {life_state} > 0" .format(poi=ewcfg.col_poi, life_state=ewcfg.col_life_state), (id_server, exposed_pois)) deathreport = "" resp_cont = ewutils.EwResponseContainer(id_server=id_server) for user in users: user_data = EwUser(id_user=user[0], id_server=id_server) if user_data.life_state == ewcfg.life_state_kingpin: continue user_poi = ewcfg.id_to_poi.get(user_data.poi) player_data = EwPlayer(id_server=user_data.id_server, id_user=user_data.id_user) protected = False slimeoid_protected = False if user_data.weapon >= 0: weapon_item = EwItem(id_item=user_data.weapon) if weapon_item.item_props.get( 'weapon_type') in ewcfg.rain_protection: protected = True cosmetics = ewitem.inventory( id_user=user_data.id_user, id_server=id_server, item_type_filter=ewcfg.it_cosmetic) for cosmetic in cosmetics: cosmetic_data = EwItem(id_item=cosmetic.get('id_item')) if cosmetic_data.item_props.get( 'id_cosmetic') in ewcfg.rain_protection: if cosmetic_data.item_props.get('adorned') == 'true': protected = True elif cosmetic_data.item_props.get( 'slimeoid') == 'true': slimeoid_protected = True if not protected: if user_data.life_state == ewcfg.life_state_shambler: slime_gain = (ewcfg.slimes_shambler - user_data.slimes) / 10 slime_gain = max(0, int(slime_gain)) user_data.change_slimes(n=slime_gain, source=ewcfg.source_weather) else: if random.random() < 0.01: user_data.degradation += 1 user_data.persist() if not slimeoid_protected: slimeoid_data = EwSlimeoid(id_user=user_data.id_user, id_server=id_server) if slimeoid_data.life_state != ewcfg.slimeoid_state_active: continue slimeoid_response = "" if random.randrange(10) < slimeoid_data.level: slimeoid_response = "*{uname}*: {slname} cries out in pain, as it's hit by the bicarbonate rain.".format( uname=player_data.display_name, slname=slimeoid_data.name) else: item_props = { 'context': ewcfg.context_slimeoidheart, 'subcontext': slimeoid_data.id_slimeoid, 'item_name': "Heart of {}".format(slimeoid_data.name), 'item_desc': "A poudrin-like crystal. If you listen carefully you can hear something that sounds like a faint heartbeat." } ewitem.item_create(id_user=str(user_data.id_user), id_server=id_server, item_type=ewcfg.it_item, item_props=item_props) slimeoid_data.die() slimeoid_data.persist() slimeoid_response = "*{uname}*: {slname} lets out a final whimper as it's dissolved by the bicarbonate rain. {skull} You quickly pocket its heart.".format( uname=player_data.display_name, slname=slimeoid_data.name, skull=ewcfg.emote_slimeskull) resp_cont.add_channel_response(user_poi.channel, slimeoid_response) for poi in exposed_pois: district_data = EwDistrict(district=poi, id_server=id_server) slimes_to_erase = district_data.slimes * 0.01 * ewcfg.weather_tick_length slimes_to_erase = max(slimes_to_erase, ewcfg.weather_tick_length * 1000) slimes_to_erase = min(district_data.slimes, slimes_to_erase) #round up or down, randomly weighted remainder = slimes_to_erase - int(slimes_to_erase) if random.random() < remainder: slimes_to_erase += 1 slimes_to_erase = int(slimes_to_erase) district_data.change_slimes(n=-slimes_to_erase, source=ewcfg.source_weather) district_data.persist() enemies = ewutils.execute_sql_query( "SELECT id_enemy FROM enemies WHERE id_server = %s AND {poi} IN %s AND {life_state} = %s AND {weathertype} != %s" .format(poi=ewcfg.col_enemy_poi, life_state=ewcfg.col_enemy_life_state, weathertype=ewcfg.col_enemy_weathertype), (id_server, exposed_pois, ewcfg.enemy_lifestate_alive, ewcfg.enemy_weathertype_rainresist)) for enemy in enemies: enemy_data = EwEnemy(id_enemy=enemy[0]) enemy_poi = ewcfg.id_to_poi.get(enemy_data.poi) slimes_to_erase = enemy_data.slimes * 0.01 * ewcfg.weather_tick_length slimes_to_erase = max(slimes_to_erase, ewcfg.weather_tick_length * 1000) slimes_to_erase = min(enemy_data.slimes, slimes_to_erase) #round up or down, randomly weighted remainder = slimes_to_erase - int(slimes_to_erase) if random.random() < remainder: slimes_to_erase += 1 slimes_to_erase = int(slimes_to_erase) enemy_data.change_slimes(n=-slimes_to_erase, source=ewcfg.source_weather) enemy_data.persist() response = "{name} takes {slimeloss:,} damage from the bicarbonate rain.".format( name=enemy_data.display_name, slimeloss=slimes_to_erase) resp_cont.add_channel_response(enemy_poi.channel, response) if enemy_data.slimes <= 0: ewhunting.delete_enemy(enemy_data) deathreport = "{skull} {name} is dissolved by the bicarbonate rain. {skull}".format( skull=ewcfg.emote_slimeskull, name=enemy_data.display_name) resp_cont.add_channel_response(enemy_poi.channel, deathreport) await resp_cont.post() except: ewutils.logMsg( "Error occurred in weather tick for server {}".format( id_server))
async def disembark(cmd): # can only use movement commands in location channels if ewmap.channel_name_is_poi(cmd.message.channel.name) == False: return await ewutils.send_message(cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, "You must {} in a zone's channel.".format(cmd.tokens[0]))) user_data = EwUser(member = cmd.message.author) response = "" resp_cont = ewutils.EwResponseContainer(client = cmd.client, id_server = user_data.id_server) # can only disembark when you're on a transport vehicle if user_data.poi in ewcfg.transports: transport_data = EwTransport(id_server = user_data.id_server, poi = user_data.poi) response = "{}ing.".format(cmd.tokens[0][1:].lower()).capitalize() # schedule tasks for concurrent execution message_task = asyncio.ensure_future(ewutils.send_message(cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, response))) wait_task = asyncio.ensure_future(asyncio.sleep(5)) # Take control of the move for this player. ewmap.move_counter += 1 move_current = ewutils.moves_active[cmd.message.author.id] = ewmap.move_counter await message_task await wait_task # check if the user entered another movement command while waiting for the current one to be completed if move_current != ewutils.moves_active[cmd.message.author.id]: return user_data = EwUser(member = cmd.message.author) transport_data = EwTransport(id_server = user_data.id_server, poi = transport_data.poi) # cancel move, if the user has left the transport while waiting for movement to be completed (e.g. by dying) if user_data.poi != transport_data.poi: return stop_poi = ewcfg.id_to_poi.get(transport_data.current_stop) # juvies can't swim if transport_data.current_stop == ewcfg.poi_id_slimesea and user_data.life_state != ewcfg.life_state_corpse: if user_data.life_state == ewcfg.life_state_kingpin: response = "You try to heave yourself over the railing as you're hit by a sudden case of sea sickness. You puke into the sea and sink back on deck." response = ewutils.formatMessage(cmd.message.author, response) return await ewutils.send_message(cmd.client, cmd.message.channel, response) user_data.poi = ewcfg.poi_id_slimesea die_resp = user_data.die(cause = ewcfg.cause_drowning) user_data.persist() resp_cont.add_response_container(die_resp) response = "{} jumps over the railing of the ferry and promptly drowns in the slime sea.".format(cmd.message.author.display_name) resp_cont.add_channel_response(channel = ewcfg.channel_slimesea, response = response) resp_cont.add_channel_response(channel = ewcfg.channel_ferry, response = response) await ewrolemgr.updateRoles(client = cmd.client, member = cmd.message.author) # they also can't fly elif transport_data.transport_type == ewcfg.transport_type_blimp and not stop_poi.is_transport_stop and user_data.life_state != ewcfg.life_state_corpse: if user_data.life_state == ewcfg.life_state_kingpin: response = "Your life flashes before your eyes, as you plummet towards your certain death. A lifetime spent being a piece of shit and playing videogames all day. You close your eyes and... BOING! You open your eyes again to see a crew of workers transporting the trampoline that broke your fall. You get up and dust yourself off, sighing heavily." response = ewutils.formatMessage(cmd.message.author, response) resp_cont.add_channel_response(channel = stop_poi.channel, response = response) user_data.poi = stop_poi.id_poi await ewrolemgr.updateRoles(client = cmd.client, member = cmd.message.author) return await resp_cont.post() district_data = EwDistrict(id_server = user_data.id_server, district = stop_poi.id_poi) district_data.change_slimes(n = user_data.slimes) district_data.persist() user_data.poi = stop_poi.id_poi die_resp = user_data.die(cause = ewcfg.cause_falling) user_data.persist() resp_cont.add_response_container(die_resp) response = "SPLAT! A body collides with the asphalt with such force, that it is utterly annihilated, covering bystanders in blood and slime and guts." resp_cont.add_channel_response(channel = stop_poi.channel, response = response) await ewrolemgr.updateRoles(client = cmd.client, member = cmd.message.author) # update user location, if move successful else: user_data.poi = transport_data.current_stop user_data.persist() response = "You enter {}".format(stop_poi.str_name) await ewrolemgr.updateRoles(client = cmd.client, member = cmd.message.author) return await ewutils.send_message(cmd.client, ewutils.get_channel(cmd.message.server, stop_poi.channel), ewutils.formatMessage(cmd.message.author, response)) return await resp_cont.post() else: response = "You are not currently riding any transport." return await ewutils.send_message(cmd.client, cmd.message.channel, ewutils.formatMessage(cmd.message.author, response))
async def on_ready(): global init_complete if init_complete: return init_complete = True ewcfg.set_client(client) ewutils.logMsg('Logged in as {} ({}).'.format(client.user.name, client.user.id)) ewutils.logMsg("Loaded NLACakaNM world map. ({}x{})".format(ewmap.map_width, ewmap.map_height)) ewmap.map_draw() # Flatten role names to all lowercase, no spaces. fake_observer = EwUser() fake_observer.life_state = ewcfg.life_state_observer for poi in ewcfg.poi_list: if poi.role != None: poi.role = ewutils.mapRoleName(poi.role) neighbors = [] neighbor_ids = [] if poi.coord != None: neighbors = ewmap.path_to(coord_start = poi.coord, user_data = fake_observer) #elif poi.id_poi == ewcfg.poi_id_thesewers: # neighbors = ewcfg.poi_list if neighbors != None: for neighbor in neighbors: neighbor_ids.append(neighbor.id_poi) ewcfg.poi_neighbors[poi.id_poi] = set(neighbor_ids) ewutils.logMsg("Found neighbors for poi {}: {}".format(poi.id_poi, ewcfg.poi_neighbors[poi.id_poi])) for id_poi in ewcfg.landmark_pois: ewutils.logMsg("beginning landmark precomputation for " + id_poi) poi = ewcfg.id_to_poi.get(id_poi) ewmap.landmarks[id_poi] = ewmap.score_map_from( coord_start = poi.coord, user_data = fake_observer, landmark_mode = True ) ewutils.logMsg("finished landmark precomputation") try: await client.change_presence(game = discord.Game(name = "EW " + ewcfg.version)) except: ewutils.logMsg("Failed to change_presence!") # Look for a Twitch client_id on disk. # FIXME debug - temporarily disable Twitch integration if False: twitch_client_id = ewutils.getTwitchClientId() # If no twitch client ID is available, twitch integration will be disabled. # FIXME debug - temporarily disable Twitch integration. if True: twitch_client_id = None ewutils.logMsg('Twitch integration disabled.') elif twitch_client_id == None or len(twitch_client_id) == 0: ewutils.logMsg('No twitch_client_id file found. Twitch integration disabled.') else: ewutils.logMsg("Enabled Twitch integration.") # Channels in the connected discord servers to announce to. channels_announcement = [] # Channels in the connected discord servers to send stock market updates to. Map of server ID to channel. channels_stockmarket = {} for server in client.servers: # Update server data in the database ewserver.server_update(server = server) # store the list of channels in an ewutils field ewcfg.update_server_list(server = server) # find roles and add them to the database ewrolemgr.setupRoles(client = client, id_server = server.id) # hides the names of poi roles await ewrolemgr.hideRoleNames(client = client, id_server = server.id) # Grep around for channels ewutils.logMsg("connected to server: {}".format(server.name)) for channel in server.channels: if(channel.type == discord.ChannelType.text): if(channel.name == ewcfg.channel_twitch_announcement): channels_announcement.append(channel) ewutils.logMsg("• found channel for announcements: {}".format(channel.name)) elif(channel.name == ewcfg.channel_stockexchange): channels_stockmarket[server.id] = channel ewutils.logMsg("• found channel for stock exchange: {}".format(channel.name)) # create all the districts in the database for poi_object in ewcfg.poi_list: poi = poi_object.id_poi # call the constructor to create an entry if it doesnt exist yet dist = EwDistrict(id_server = server.id, district = poi) # change the ownership to the faction that's already in control to initialize topic names try: # initialize gang bases if poi == ewcfg.poi_id_rowdyroughhouse: dist.controlling_faction = ewcfg.faction_rowdys elif poi == ewcfg.poi_id_copkilltown: dist.controlling_faction = ewcfg.faction_killers resp_cont = dist.change_ownership(new_owner = dist.controlling_faction, actor = "init", client = client) dist.persist() await resp_cont.post() except: ewutils.logMsg('Could not change ownership for {} to "{}".'.format(poi, dist.controlling_faction)) asyncio.ensure_future(ewdistrict.capture_tick_loop(id_server = server.id)) asyncio.ensure_future(ewutils.bleed_tick_loop(id_server = server.id)) asyncio.ensure_future(ewutils.enemy_action_tick_loop(id_server=server.id)) asyncio.ensure_future(ewutils.spawn_enemies_tick_loop(id_server = server.id)) asyncio.ensure_future(ewutils.burn_tick_loop(id_server = server.id)) asyncio.ensure_future(ewutils.remove_status_loop(id_server = server.id)) asyncio.ensure_future(ewworldevent.event_tick_loop(id_server = server.id)) asyncio.ensure_future(ewutils.sap_tick_loop(id_server = server.id)) if not debug: await ewtransport.init_transports(id_server = server.id) asyncio.ensure_future(ewweather.weather_tick_loop(id_server = server.id)) asyncio.ensure_future(ewslimeoid.slimeoid_tick_loop(id_server = server.id)) asyncio.ensure_future(ewfarm.farm_tick_loop(id_server = server.id)) try: ewutils.logMsg('Creating message queue directory.') os.mkdir(ewcfg.dir_msgqueue) except FileExistsError: ewutils.logMsg('Message queue directory already exists.') ewutils.logMsg('Ready.') """ Set up for infinite loop to perform periodic tasks. """ time_now = int(time.time()) time_last_pvp = time_now time_last_twitch = time_now time_twitch_downed = 0 # Every three hours we log a message saying the periodic task hook is still active. On startup, we want this to happen within about 60 seconds, and then on the normal 3 hour interval. time_last_logged = time_now - ewcfg.update_hookstillactive + 60 stream_live = None ewutils.logMsg('Beginning periodic hook loop.') while not ewutils.TERMINATE: time_now = int(time.time()) # Periodic message to log that this stuff is still running. if (time_now - time_last_logged) >= ewcfg.update_hookstillactive: time_last_logged = time_now ewutils.logMsg("Periodic hook still active.") # Check to see if a stream is live via the Twitch API. # FIXME disabled if False: #if twitch_client_id != None and (time_now - time_last_twitch) >= ewcfg.update_twitch: time_last_twitch = time_now try: # Twitch API call to see if there are any active streams. json_string = "" p = subprocess.Popen( "curl -H 'Client-ID: {}' -X GET 'https://api.twitch.tv/helix/streams?user_login = rowdyfrickerscopkillers' 2>/dev/null".format(twitch_client_id), shell = True, stdout = subprocess.PIPE ) for line in p.stdout.readlines(): json_string += line.decode('utf-8') json_parsed = json.loads(json_string) # When a stream is up, data is an array of stream information objects. data = json_parsed.get('data') if data != None: data_count = len(data) stream_was_live = stream_live stream_live = True if data_count > 0 else False if stream_was_live == True and stream_live == False: time_twitch_downed = time_now if stream_was_live == False and stream_live == True and (time_now - time_twitch_downed) > 600: ewutils.logMsg("The stream is now live.") # The stream has transitioned from offline to online. Make an announcement! for channel in channels_announcement: await ewutils.send_message( client, channel, "ATTENTION CITIZENS. THE **ROWDY F****R** AND THE **COP KILLER** ARE **STREAMING**. BEWARE OF INCREASED KILLER AND ROWDY ACTIVITY.\n\n@everyone\n{}".format( "https://www.twitch.tv/rowdyfrickerscopkillers" ) ) except: ewutils.logMsg('Twitch handler hit an exception (continuing): {}'.format(json_string)) traceback.print_exc(file = sys.stdout) # Clear PvP roles from players who are no longer flagged. if (time_now - time_last_pvp) >= ewcfg.update_pvp: time_last_pvp = time_now try: for server in client.servers: role_ids = [] for pvp_role in ewcfg.role_to_pvp_role.values(): role = ewrolemgr.EwRole(id_server = server.id, name = pvp_role) role_ids.append(role.id_role) # Monitor all user roles and update if a user is no longer flagged for PvP. for member in server.members: for role in member.roles: if role.id in role_ids: await ewrolemgr.updateRoles(client = client, member = member) break except: ewutils.logMsg('An error occurred in the scheduled role update task:') traceback.print_exc(file=sys.stdout) # Adjust the exchange rate of slime for the market. try: for server in client.servers: # Load market data from the database. market_data = EwMarket(id_server = server.id) if market_data.time_lasttick + ewcfg.update_market <= time_now: market_response = "" for stock in ewcfg.stocks: s = EwStock(server.id, stock) # we don't update stocks when they were just added if s.timestamp != 0: s.timestamp = time_now market_response = ewmarket.market_tick(s, server.id) await ewutils.send_message(client, channels_stockmarket.get(server.id), market_response) market_data = EwMarket(id_server = server.id) market_data.time_lasttick = time_now # Advance the time and potentially change weather. market_data.clock += 1 if market_data.clock >= 24 or market_data.clock < 0: market_data.clock = 0 market_data.day += 1 if market_data.clock == 6: # Update the list of available bazaar items by clearing the current list and adding the new items market_data.bazaar_wares.clear() bazaar_foods = [] bazaar_cosmetics = [] bazaar_general_items = [] bazaar_furniture = [] for item in ewcfg.vendor_inv.get(ewcfg.vendor_bazaar): if item in ewcfg.item_names: bazaar_general_items.append(item) elif item in ewcfg.food_names: bazaar_foods.append(item) elif item in ewcfg.cosmetic_names: bazaar_cosmetics.append(item) elif item in ewcfg.furniture_names: bazaar_furniture.append(item) market_data.bazaar_wares['slimecorp1'] = ewcfg.weapon_id_umbrella market_data.bazaar_wares['slimecorp2'] = ewcfg.cosmetic_id_raincoat market_data.bazaar_wares['generalitem'] = random.choice(bazaar_general_items) market_data.bazaar_wares['food1'] = random.choice(bazaar_foods) # Don't add repeated foods bw_food2 = None while bw_food2 is None or bw_food2 in market_data.bazaar_wares.values(): bw_food2 = random.choice(bazaar_foods) market_data.bazaar_wares['food2'] = bw_food2 market_data.bazaar_wares['cosmetic1'] = random.choice(bazaar_cosmetics) # Don't add repeated cosmetics bw_cosmetic2 = None while bw_cosmetic2 is None or bw_cosmetic2 in market_data.bazaar_wares.values(): bw_cosmetic2 = random.choice(bazaar_cosmetics) market_data.bazaar_wares['cosmetic2'] = bw_cosmetic2 bw_cosmetic3 = None while bw_cosmetic3 is None or bw_cosmetic3 in market_data.bazaar_wares.values(): bw_cosmetic3 = random.choice(bazaar_cosmetics) market_data.bazaar_wares['cosmetic3'] = bw_cosmetic3 bw_furniture2 = None while bw_furniture2 is None or bw_furniture2 in market_data.bazaar_wares.values(): bw_furniture2 = random.choice(bazaar_furniture) market_data.bazaar_wares['furniture2'] = bw_furniture2 bw_furniture3 = None while bw_furniture3 is None or bw_furniture3 in market_data.bazaar_wares.values(): bw_furniture3 = random.choice(bazaar_furniture) market_data.bazaar_wares['furniture3'] = bw_furniture3 if random.random() == 0.1: market_data.bazaar_wares['minigun'] = ewcfg.weapon_id_minigun market_data.persist() if not ewutils.check_fursuit_active(market_data.id_server): ewcosmeticitem.dedorn_all_costumes() if market_data.clock == 6 and market_data.day % 8 == 0: await ewapt.rent_time(id_server=server.id) market_data = EwMarket(id_server=server.id) market_data.persist() if market_data.clock == 6: response = ' The SlimeCorp Stock Exchange is now open for business.' await ewutils.send_message(client, channels_stockmarket.get(server.id), response) elif market_data.clock == 20: response = ' The SlimeCorp Stock Exchange has closed for the night.' await ewutils.send_message(client, channels_stockmarket.get(server.id), response) market_data = EwMarket(id_server = server.id) if random.randrange(3) == 0: pattern_count = len(ewcfg.weather_list) if pattern_count > 1: weather_old = market_data.weather if random.random() < 0.4: market_data.weather = ewcfg.weather_bicarbonaterain # Randomly select a new weather pattern. Try again if we get the same one we currently have. while market_data.weather == weather_old: pick = random.randrange(len(ewcfg.weather_list)) market_data.weather = ewcfg.weather_list[pick].name # Log message for statistics tracking. ewutils.logMsg("The weather changed. It's now {}.".format(market_data.weather)) # Persist new data. market_data.persist() # Decay slime totals ewutils.decaySlimes(id_server = server.id) # Increase hunger for all players below the max. #ewutils.pushupServerHunger(id_server = server.id) # Decrease inebriation for all players above min (0). ewutils.pushdownServerInebriation(id_server = server.id) # Remove fish offers which have timed out ewfish.kill_dead_offers(id_server = server.id) # kill advertisements that have timed out ewads.delete_expired_ads(id_server = server.id) await ewdistrict.give_kingpins_slime_and_decay_capture_points(id_server = server.id) await ewmap.kick(server.id) # Post leaderboards at 6am NLACakaNM time. if market_data.clock == 6: await ewleaderboard.post_leaderboards(client = client, server = server) except: ewutils.logMsg('An error occurred in the scheduled slime market update task:') traceback.print_exc(file = sys.stdout) # Parse files dumped into the msgqueue directory and send messages as needed. try: for msg_file in os.listdir(ewcfg.dir_msgqueue): fname = "{}/{}".format(ewcfg.dir_msgqueue, msg_file) msg = ewutils.readMessage(fname) os.remove(fname) msg_channel_names = [] msg_channel_names_reverb = [] if msg.channel != None: msg_channel_names.append(msg.channel) if msg.poi != None: poi = ewcfg.id_to_poi.get(msg.poi) if poi != None: if poi.channel != None and len(poi.channel) > 0: msg_channel_names.append(poi.channel) if msg.reverb == True: pois_adjacent = ewmap.path_to(poi_start = msg.poi) for poi_adjacent in pois_adjacent: if poi_adjacent.channel != None and len(poi_adjacent.channel) > 0: msg_channel_names_reverb.append(poi_adjacent.channel) if len(msg_channel_names) == 0: ewutils.logMsg('in file {} message for channel {} (reverb {})\n{}'.format(msg_file, msg.channel, msg.reverb, msg.message)) else: # Send messages to every connected server. for server in client.servers: for channel in server.channels: if channel.name in msg_channel_names: await ewutils.send_message(client, channel, "**{}**".format(msg.message)) elif channel.name in msg_channel_names_reverb: await ewutils.send_message(client, channel, "**Something is happening nearby...\n\n{}**".format(msg.message)) except: ewutils.logMsg('An error occurred while trying to process the message queue:') traceback.print_exc(file = sys.stdout) # Wait a while before running periodic tasks. await asyncio.sleep(15)