def logic(entity): _last_pos = None _stop_here = False for node_id in entity['node_grid']['path'][:]: _node = entity['node_grid']['nodes'][node_id] if not (_node['node']['x'], _node['node']['y']) == movement.get_position(entity): if _stop_here and not (_node['node']['x'], _node['node']['y']) == _last_pos: break _distance = numbers.distance((_node['node']['x'], _node['node']['y']), movement.get_position(entity)) if _node['call_on_touch'] and _distance: continue elif not _distance: entity['node_grid']['path'].remove(node_id) del entity['node_grid']['nodes'][node_id] entities.delete_entity_via_id(node_id) _node['callback']() if not _node['passive']: _stop_here = True _last_pos = (_node['node']['x'], _node['node']['y'])
def check_for_collisions(entity): _x, _y = movement.get_position(entity) if _x < 0 or _x >= zones.get_active_size( )[0] - 1 or _y < 0 or _y >= zones.get_active_size()[1] - 1: entities.delete_entity(entity) return if (_x, _y) in zones.get_active_solids(entity): entities.trigger_event(entity, 'collision_with_solid') return for entity_id in entities.get_entity_group('life'): if entity_id == entity['owner']: continue if movement.get_position(entity) == movement.get_position_via_id( entity_id): entities.trigger_event(entity, 'collision_with_entity', target_id=entity_id) return
def build_item_list(entity): entity['ai']['visible_items'] = {'weapon': [], 'container': [], 'ammo': [], 'bullet': [], 'corpse': []} return _active_solids = zones.get_active_solids(entity) for entity_id in entities.get_entity_group('items'): _item = entities.get_entity(entity_id) if not _item['stats']['type'] in entity['ai']['visible_items']: continue if _item['stats']['owner']: continue _distance = numbers.distance(movement.get_position(entity), movement.get_position(_item)) if _distance >= stats.get_vision(entity): continue for pos in shapes.line(movement.get_position(entity), movement.get_position(_item)): if pos in _active_solids: break else: entity['ai']['visible_items'][_item['stats']['type']].append(entity_id) entities.trigger_event(_item, 'seen', target_id=entity['_id'])
def create_noise(entity, text, volume, owner_can_hear=False, show_on_sight=False, direction=-1000, callback=None, context_callback=None): _x, _y = movement.get_position(entity) for entity_id in entities.get_entity_group('life'): if not owner_can_hear and entity['_id'] == entity_id: continue _target = entities.get_entity(entity_id) if entity['ai']['faction'] == _target['ai']['faction']: continue #TODO: Hearing stat _distance = numbers.distance(movement.get_position(entity), movement.get_position(_target)) _accuracy = 1 - numbers.clip(_distance / float(volume), 0, 1) entities.trigger_event(_target, 'heard_noise', x=_x, y=_y, text=text, direction=direction, show_on_sight=show_on_sight, accuracy=_accuracy, callback=callback, context_callback=context_callback)
def _locate_npc_message(goal, member_id): _target_id = goal['target_id'] _member = entities.get_entity(member_id) _mission = entities.get_entity(goal['mission_id']) if not _target_id in _member['ai']['life_memory'] or not _member['ai']['life_memory'][_target_id]['last_seen_at']: goal['message'] = 'Gather location info on target.' return if _member['ai']['life_memory'][_target_id]['is_dead']: goal['message'] = 'Confirmed: Target is dead.' entities.trigger_event(_member, 'complete_goal', mission_id=goal['mission_id'], goal_id=goal['_id']) elif _member['ai']['life_memory'][_target_id]['can_see']: goal['message'] = 'Target in line of sight.' entities.trigger_event(_member, 'complete_goal', mission_id=goal['mission_id'], goal_id=goal['_id']) elif _member['ai']['life_memory'][_target_id]['last_seen_at']: _direction = numbers.direction_to(movement.get_position(_member), _member['ai']['life_memory'][_target_id]['last_seen_at']) _distance = numbers.distance(movement.get_position(_member), _member['ai']['life_memory'][_target_id]['last_seen_at']) _real_direction = conversions.get_real_direction(_direction) _real_distance = conversions.get_real_distance(_distance) goal['message'] = 'Target last seen %s meters to the %s' % (_real_distance, _real_direction) _member['ai']['life_memory'][_target_id]['mission_related'] = True
def handle_keyboard_input(): if controls.get_input_char_pressed('\t'): if settings.TICK_MODE == 'strategy': if ui_panel.ACTIVE_MENU: ui_panel.close() else: ui_panel.show_inventory(entity) else: _x, _y = movement.get_position(entity) camera.set_pos(_x - constants.MAP_VIEW_WIDTH / 2, _y - constants.MAP_VIEW_HEIGHT / 2) if controls.get_input_char_pressed('O'): settings.toggle_show_node_grid() elif controls.get_input_char_pressed('o'): settings.toggle_observer_mode() if controls.get_input_char_pressed('d'): _mx, _my = ui_cursor.get_map_position() for entity_id in entities.get_entity_group('life'): _entity = entities.get_entity(entity_id) if not numbers.distance( (_mx, _my), movement.get_position(_entity)): _x, _y = ui_cursor.get_screen_position() _menu = ui_menu.create(_x, _y, title='Debug') ui_menu.add_selectable(_menu, 'Show Metas', lambda: _show_metas(_entity)) ui_menu.add_selectable( _menu, 'Kill', lambda: entities.trigger_event(_entity, 'kill')) ui_menu.add_selectable(_menu, 'Overwatch', lambda: ai_debugger.register(_entity)) break if controls.get_input_char_pressed('l'): _x, _y = ui_cursor.get_screen_position() _mx, _my = ui_cursor.get_map_position() _weight = zones.get_active_weight_map()[_my, _mx] _menu = ui_menu.create(_x, _y, title='Tile Info') ui_menu.add_selectable( _menu, 'Warp', lambda: entities.trigger_event( entity, 'set_position', x=_mx, y=_my)) ui_menu.add_selectable( _menu, 'Light', lambda: effects.light(_mx, _my, 15, r=random.uniform(1.0, 1.5), g=random.uniform(1.0, 1.5), light_map='static_lighting')) ui_menu.add_selectable(_menu, 'Weight: %s' % _weight, lambda: _)
def can_see_position(entity, position): _solids = zones.get_active_solids(entity) if numbers.distance(movement.get_position(entity), position) > stats.get_vision(entity): return False for pos in shapes.line(movement.get_position(entity), position): if pos in _solids: return False return True
def get_cover_position(squad, member_id): _member = entities.get_entity(member_id) _best_coverage = {'position': None, 'score': 0} _inside = zones.get_active_inside_positions() if _member['movement']['path']['destination']: _hide_pos = _member['movement']['path']['destination'] else: _hide_pos = movement.get_position(_member) if _hide_pos in squad['position_map_scores']: _scores = squad['position_map_scores'][_hide_pos] _score = _scores['coverage'] + _scores['member_coverage'] if not _scores['targets'] and _score > 0: return _hide_pos for pos in squad['position_map_scores']: _scores = squad['position_map_scores'][pos] #TODO: Add or subtract here? Subtraction will make some NPCs run away from teammates _score = _scores['coverage'] + _scores['member_coverage'] if not pos in _inside: continue if _scores['targets'] or _score <= 0: continue if _score > _best_coverage['score']: _best_coverage['score'] = _score _best_coverage['position'] = pos[:] if not _best_coverage['position']: #print 'no good coverage position' return _x, _y = movement.get_position(_member) for coverage_pos in shapes.circle(_best_coverage['position'][0], _best_coverage['position'][1], 6): if not coverage_pos in squad['position_map_scores']: continue _c_dist = 10 * (1 - (numbers.distance(coverage_pos, (_x, _y)) / 3.0)) squad['position_map_scores'][coverage_pos][ 'member_coverage'] += _c_dist squad['position_map_scores'][ _best_coverage['position']]['member_coverage'] += 15 return _best_coverage['position']
def get_nearest_entity_in_list(entity, entity_list): _nearest_entity = {'entity': None, 'distance': 0} for entity_id in entity_list: _entity = entities.get_entity(entity_id) _distance = numbers.distance(movement.get_position(entity), movement.get_position(_entity)) if not _nearest_entity['entity'] or _distance < _nearest_entity['distance']: _nearest_entity['entity'] = _entity _nearest_entity['distance'] = _distance return _nearest_entity['entity']
def get_nearest_entity_in_list(entity, entity_list): _nearest_entity = {'entity': None, 'distance': 0} for entity_id in entity_list: _entity = entities.get_entity(entity_id) _distance = numbers.distance(movement.get_position(entity), movement.get_position(_entity)) if not _nearest_entity[ 'entity'] or _distance < _nearest_entity['distance']: _nearest_entity['entity'] = _entity _nearest_entity['distance'] = _distance return _nearest_entity['entity']
def get_cover_position(squad, member_id): _member = entities.get_entity(member_id) _best_coverage = {'position': None, 'score': 0} _inside = zones.get_active_inside_positions() if _member['movement']['path']['destination']: _hide_pos = _member['movement']['path']['destination'] else: _hide_pos = movement.get_position(_member) if _hide_pos in squad['position_map_scores']: _scores = squad['position_map_scores'][_hide_pos] _score = _scores['coverage'] + _scores['member_coverage'] if not _scores['targets'] and _score > 0: return _hide_pos for pos in squad['position_map_scores']: _scores = squad['position_map_scores'][pos] #TODO: Add or subtract here? Subtraction will make some NPCs run away from teammates _score = _scores['coverage'] + _scores['member_coverage'] if not pos in _inside: continue if _scores['targets'] or _score <= 0: continue if _score > _best_coverage['score']: _best_coverage['score'] = _score _best_coverage['position'] = pos[:] if not _best_coverage['position']: #print 'no good coverage position' return _x, _y = movement.get_position(_member) for coverage_pos in shapes.circle(_best_coverage['position'][0], _best_coverage['position'][1], 6): if not coverage_pos in squad['position_map_scores']: continue _c_dist = 10 * (1 - (numbers.distance(coverage_pos, (_x, _y)) / 3.0)) squad['position_map_scores'][coverage_pos]['member_coverage'] += _c_dist squad['position_map_scores'][_best_coverage['position']]['member_coverage'] += 15 return _best_coverage['position']
def bullet(entity, x, y, tx, ty, speed, accuracy, damage): _entity = _create(x, y, 'Bullet', '.', 0, 'bullet') _entity['owner'] = entity['_id'] _entity['start_position'] = (x, y) _entity['end_position'] = (tx, ty) _entity['speed'] = speed _entity['damage'] = damage entities.add_entity_to_group(_entity, 'bullets') timers.register(_entity) entities.trigger_event(_entity, 'set_direction', direction=numbers.direction_to( (x, y), (tx, ty)) + random.uniform(-accuracy, accuracy)) entities.trigger_event(_entity, 'create_timer', time=speed, repeat=-1, enter_callback=_bullet_tick, repeat_callback=_bullet_tick) entities.register_event(_entity, 'position_changed', lambda e, **kwargs: check_for_collisions(e)) entities.register_event( _entity, 'collision_with_entity', lambda e, target_id: entities. trigger_event(entities.get_entity(target_id), 'hit', projectile=e)) entities.register_event(_entity, 'collision_with_entity', lambda e, target_id: entities.delete_entity(e)) entities.register_event( _entity, 'collision_with_solid', lambda e: effects.light( movement.get_position(e)[0], movement.get_position(e)[1], random.randint(3, 4))) entities.register_event(_entity, 'collision_with_solid', lambda e: entities.delete_entity(e)) entities.register_event( _entity, 'collision_with_solid', lambda e: effects.smoke_cloud(movement.get_position(e)[0], movement.get_position(e)[1], random.uniform(2, 2.75), start_alpha=random.uniform(0.45, .65), decay_amount=1.5)) entities.register_event(_entity, 'check_next_position', check_next_position) if not '--no-fx' in sys.argv: entities.register_event( _entity, 'position_changed', lambda e, x, y, **kwargs: _bullet_effects(e, x, y))
def frag_grenade_explode(entity): _x, _y = movement.get_position(entity) _damage = entity['damage'] _size = 3 * int(round((_damage * .01))) effects.explosion(_x, _y, _size) for entity_id in entities.get_entity_group('life'): _entity = entities.get_entity(entity_id) _distance = numbers.distance((_x, _y), movement.get_position(_entity)) if _distance - 1 > _size or not life.can_see_position(_entity, (_x, _y)): continue entities.trigger_event(_entity, 'hit', projectile=entity, damage_mod=1 - ((_distance - 1) / float(_size)))
def get_push_position(squad, member_id): _member = entities.get_entity(member_id) _best_vantage = {'position': None, 'score': 1000} _vision = stats.get_vision(_member) _engage_range = int(round(_vision * .75)) for pos in squad['position_map_scores']: _scores = squad['position_map_scores'][pos] _score = _scores['vantage'] + _scores['member_coverage'] if not _scores['targets'] or _score < 6 or _score > _engage_range: continue if _score < _best_vantage['score']: _best_vantage['score'] = _score _best_vantage['position'] = pos[:] if not _best_vantage['position']: _member['ai']['meta']['has_firing_position'] = False return _x, _y = movement.get_position(_member) for coverage_pos in shapes.circle(_best_vantage['position'][0], _best_vantage['position'][1], 6): if not coverage_pos in squad['position_map_scores']: continue _c_dist = 15 * (1 - (numbers.distance(coverage_pos, (_x, _y)) / 6.0)) squad['position_map_scores'][coverage_pos]['member_coverage'] += _c_dist squad['position_map_scores'][_best_vantage['position']]['member_coverage'] += 20 return _best_vantage['position']
def _smoke_shooter_push(entity): _x, _y = movement.get_position(entity) _direction = movement.get_direction(entity) _mod = random.randint(-35, 35) _alpha = flags.get_flag(entity, 'alpha') if _mod < 0: _mod = numbers.clip(_mod, -35, -20) else: _mod = numbers.clip(_mod, 20, 35) _direction += _mod _v_x, _v_y = numbers.velocity(_direction, random.uniform(.65, .85)) if not int(round(_x + _v_x)) == int(round(_x)) or not int(round(_y + _v_y)) == int(round(_y)): #smoke_cloud(_x + _v_x, _y + _v_y, random.randint(1, 2), start_alpha=_alpha, decay_amount=1.2) smoke(_x + _v_x, _y + _v_y, .75, start_amount=_alpha, decay_amount=random.uniform(3.0, 4.0)) _x += _v_x _y += _v_y if (int(round(_x)), int(round(_y))) in zones.get_active_solids({}, no_life=True): entities.delete_entity(entity) return entities.trigger_event(entity, 'set_direction', direction=_direction) entities.trigger_event(entity, 'set_position', x=_x, y=_y) entities.trigger_event(entity, 'set_flag', flag='alpha', value=_alpha - .05)
def _tick_fire(entity): _x, _y = movement.get_position(entity) _alpha = flags.get_flag(entity, 'alpha') _alpha += random.uniform(-.3, .3) _alpha = numbers.clip(_alpha, 0, 1) if not _alpha: #char(_x, _y, numbers.clip(flags.get_flag(entity, 'alpha_max') - random.uniform(.1, .2), 0, 1)) entities.delete_entity(entity) return #entities.trigger_event(entity, 'set_char', char=random.choice(['*', '&', '%'])) _color = list(display.get_color_at('tiles', _x, _y)) _color[0] = numbers.interp_velocity(_color[0], random.choice([constants.FIRE_1, constants.FIRE_2, constants.FIRE_3]), _alpha) _color[1] = numbers.interp_velocity(_color[1], random.choice([constants.FIRE_1, constants.FIRE_2, constants.FIRE_3]), _alpha) for c in range(len(_color)): for i in range(len(_color)): _color[c][i] = int((round(_color[c][i]))) entities.trigger_event(entity, 'set_fore_color', color=_color[0]) entities.trigger_event(entity, 'set_back_color', color=_color[1]) entities.trigger_event(entity, 'set_flag', flag='alpha', value=_alpha)
def draw_path(entity, x_mod=0, y_mod=0): _last_x, _last_y = (0, 0) _node_ids = entity['node_grid']['path'][:] _action_time_max = 0 _surface_width = display.get_surface('nodes')['width'] _surface_height = display.get_surface('nodes')['height'] for node_id in _node_ids: _node = entity['node_grid']['nodes'][node_id] if not _last_x: _last_x, _last_y = movement.get_position(entity) if (_last_x, _last_y) == (_node['node']['x'], _node['node']['y']): continue _node['node']['busy_pos'] = [] if _node['node']['draw_path'] and not _node['node']['path']: _path = pathfinding.astar((_last_x, _last_y), (_node['node']['x'], _node['node']['y']), zones.get_active_astar_map(), zones.get_active_weight_map()) if (_node['node']['x'], _node['node']['y']) in _path: _path.remove((_node['node']['x'], _node['node']['y'])) _node['node']['path'] = _path _move_cost = 0 for pos in _node['node']['path']: for node_id in _node_ids: _check_node = entity['node_grid']['nodes'][node_id]['node'] if not _check_node['action_time']: continue if (_check_node['x'], _check_node['y']) == pos: _action_time_max = _check_node['action_time'] if _action_time_max and _move_cost <= _action_time_max: _color_mod = int(round(200*numbers.clip(_move_cost/float(_action_time_max), .75, 1))) _color = (_color_mod, 0, 0) _node['node']['busy_pos'].append(pos) else: _color = (200, 200, 200) if _action_time_max: _move_cost += movement.get_move_cost(entity) if _move_cost >= _action_time_max: _action_time_max = 0 _move_cost = 0 if pos[0]-x_mod < 0 or pos[1]-y_mod < 0 or pos[0]-x_mod >= _surface_width or pos[1]-y_mod >= _surface_height: continue display.write_char('nodes', pos[0]-x_mod, pos[1]-y_mod, chr(177), fore_color=_color) if _node['node']['draw_path']: _last_x, _last_y = (_node['node']['x'], _node['node']['y'])
def create_position_map(squad): _coverage_positions = set() _known_targets = set() _known_squads = set() for member_id in squad['members']: _member = entities.get_entity(member_id) _x, _y = movement.get_position(_member) _sight = stats.get_vision(_member) if member_id in squad['member_position_maps']: _old_coverage_positions = squad['member_position_maps'][member_id].copy() else: _old_coverage_positions = set() _map_size = zones.get_active_size() squad['member_position_maps'][member_id] = set() squad['member_los_maps'][member_id] = tcod.map_new(_map_size[0], _map_size[1]) tcod.map_copy(zones.get_active_los_map(), squad['member_los_maps'][member_id]) _t = time.time() tcod.map_compute_fov(squad['member_los_maps'][member_id], _x, _y, radius=_sight, light_walls=False, algo=tcod.FOV_PERMISSIVE_2) for pos in shapes.circle(_x, _y, _sight): if pos[0] < 0 or pos[0] >= _map_size[0] or pos[1] < 0 or pos[1] >= _map_size[1]: continue if not tcod.map_is_in_fov(squad['member_los_maps'][member_id], pos[0], pos[1]): continue _coverage_positions.add(pos) squad['member_position_maps'][member_id].add(pos) #TODO: Do this elsewhere for target_id in _member['ai']['visible_targets']: if not target_id in entities.ENTITIES: continue _target = entities.get_entity(target_id) _known_squads.add((_target['ai']['faction'], _target['ai']['squad'])) #TODO: Is this right? _known_targets.update(_member['ai']['visible_targets']) _positions_to_remove = _old_coverage_positions - _coverage_positions squad['known_targets'].update(_known_targets) squad['known_squads'].update(_known_squads) squad['coverage_positions'].update(_coverage_positions) squad['coverage_positions'] = squad['coverage_positions'] - _positions_to_remove if squad['known_targets']: update_position_maps(squad) logging.debug('Updated local position map - requesting squad update') else: logging.debug('Updated local position map.')
def _search_for_target(entity, target_id): _nodes = flags.get_flag(entity, 'search_nodes') if not _nodes: flags.delete_flag(entity, 'search_nodes') entities.trigger_event(entity, 'target_search_failed', target_id=target_id) return _node_list = _nodes.keys() _node_list.sort() _node_x, _node_y = _nodes[_node_list[0]][0] _distance = numbers.distance(movement.get_position(entity), (_node_x, _node_y)) if _distance <= 15 and life.can_see_position(entity, (_node_x, _node_y)): _nodes[_node_list[0]].remove((_node_x, _node_y)) if not _nodes[_node_list[0]]: del _nodes[_node_list[0]] else: movement.walk_to_position(entity, _node_x, _node_y, zones.get_active_astar_map(), zones.get_active_weight_map())
def disown(entity): if not entity['stats']['owner']: return _owner = entities.get_entity(entity['stats']['owner']) _x, _y = movement.get_position(_owner) entities.trigger_event(entity, 'set_position', x=_x, y=_y) if entity['stats']['type'] == 'container': for item_id in entity['inventory']['containers'][entity['_id']]: _item = entities.get_entity(item_id) disown(_item) del entity['inventory']['containers'][entity['_id']] if entity['stats']['in_container']: _owner['inventory']['containers'][entity['stats']['in_container']]['items'].remove(entity['_id']) _owner['inventory']['containers'][entity['stats']['in_container']]['weight'] -= entity['stats']['weight'] entity['stats']['in_container'] = None _owner['inventory']['items'].remove(entity['_id']) entity['stats']['owner'] = None
def draw_item_labels(): _camera_x, _camera_y = camera.X, camera.Y _width = display.get_surface('life')['width'] _height = display.get_surface('life')['height'] if settings.OBSERVER_MODE: _draw_items = entities.get_entity_group('items') else: _draw_items = [item for _items in PLAYER['ai']['visible_items'].values() for item in _items] for entity_id in _draw_items: if not entity_id in entities.ENTITIES: continue _entity = entities.get_entity(entity_id) if _entity['stats']['owner']: continue _x, _y = movement.get_position(_entity) _x -= _camera_x _y -= _camera_y if _x < 0 or _y < 0 or _x >= _width or _y >= _height: continue _label = _entity['stats']['name'] _render_x = numbers.clip(_x - len(_label)/2, 0, _width - len(_label)) _render_y = numbers.clip(_y + 2, 0, _height) if _render_y == _y: _render_y -= 1 display.write_string('ui', _render_x, _render_y, _label)
def focus_on_entity(entity, target_id, show_line=False, pause=False): global HAS_FOCUS, PAUSE if HAS_FOCUS or '--no-fx' in sys.argv: return HAS_FOCUS = target_id PAUSE = pause _entity = ui_dialog.create(18, 7, 'Enemy spotted!') entities.register_event(_entity, 'delete', lambda e: lose_focus()) entities.trigger_event(DIRECTOR, 'create_timer', time=120, exit_callback=lambda e: ui_dialog.delete(_entity)) if show_line: for x, y in shapes.line(movement.get_position(entity), movement.get_position_via_id(target_id)): effects.vapor(x, y, group='effects_freetick', start_alpha=1.0, fade_rate=.01)
def _get_item(entity, item_id, hold=False, weight=None): _item = entities.get_entity(item_id) _x, _y = movement.get_position(_item) _distance = numbers.distance(movement.get_position(entity), (_x, _y)) if weight: ai.set_meta_weight(entity, weight, 10*numbers.clip(_distance/30.0, 0, 1)) if _distance: movement.walk_to_position(entity, _x, _y, zones.get_active_astar_map(), zones.get_active_weight_map(), smp=True) else: if hold: life.get_and_hold_item(entity, item_id) else: life.get_and_store_item(entity, item_id)
def _explosive_tick(entity): _direction = movement.get_direction(entity) entities.trigger_event(entity, 'push_tank', direction=_direction) _x, _y = movement.get_position(entity) _distance = numbers.distance((_x, _y), entity['end_position']) _starting_target_distance = numbers.distance(entity['start_position'], entity['end_position']) if _distance <= entity['accuracy'] * 2.5: entity['slow_down'] = True if entity['slow_down']: entity['speed'] = numbers.clip(entity['speed'] * 1.2, 0, 40) if entity['speed'] < 40: entities.trigger_event(entity, 'create_timer', time=int(round(entity['speed'])), name='movement', exit_callback=_explosive_tick) else: entities.trigger_event(entity, 'activate_explosive')
def member_learn_raid(entity, member_id, camp): _faction = ai_factions.FACTIONS[camp['owner']['faction']] _squad = entities.get_entity(_faction['squads'][camp['owner']['squad']]) if not _squad['leader']: return _camp_leader = entities.get_entity(_squad['leader']) #TODO: Don't do this if not _camp_leader['_id'] in entity['ai']['life_memory']: life.create_life_memory(entity, _camp_leader['_id']) entity['ai']['life_memory'][_camp_leader['_id']].update({ 'is_lost': True, 'searched_for': False, 'can_see': False, 'last_seen_at': movement.get_position(_camp_leader), 'last_seen_velocity': None })
def hit(entity, projectile, damage_mod=1.0): _accuracy = random.uniform(.7, 1) _hit_map = [] for limb_name in entity['skeleton']['limbs']: _limb = entity['skeleton']['limbs'][limb_name] for i in range(int(round(_limb['health'] * _limb['accuracy']))): _hit_map.append(limb_name) _limb_name = random.choice(_hit_map) _limb = entity['skeleton']['limbs'][_limb_name] _damage = int( round((projectile['damage'] * _accuracy) * (numbers.clip( (1 - _limb['accuracy']), 0.25, .6) + .4))) _damage = int(round(_damage * damage_mod)) _limb['health'] -= _damage _x, _y = movement.get_position(entity) _x += int(round(random.uniform(-1, 1))) _y += int(round(random.uniform(-1, 1))) _mod = _limb['health'] / float(_limb['max_health']) #effects.explosion(_x, _y, 6) if not (_x, _y) in zones.get_active_solids(entity, ignore_calling_entity=True): #effects.blood(_x, _y) effects.blood_splatter( _x, _y, movement.get_direction(projectile) + random.randint(-5, 5)) entities.trigger_event(entity, 'animate', animation=['X', '@@'], repeat=4 * int(round((1 - _mod))), delay=20 * _mod) if _limb['health'] <= 0: if _limb['critical']: if projectile['owner'] in entities.ENTITIES: entities.trigger_event(entities.get_entity( projectile['owner']), 'log_kill', target_id=entity['_id']) entities.trigger_event(entity, 'killed_by', target_id=projectile['owner']) #entity['stats']['grave'] = {'':} entities.delete_entity(entity) else: if projectile['owner'] in entities.ENTITIES: entities.trigger_event(entities.get_entity(projectile['owner']), 'did_damage', target_id=entity['_id'], damage=_damage) entities.trigger_event(entity, 'damage', limb=_limb_name, damage=_damage)
def disown(entity): if not entity['stats']['owner']: return _owner = entities.get_entity(entity['stats']['owner']) _x, _y = movement.get_position(_owner) entities.trigger_event(entity, 'set_position', x=_x, y=_y) if entity['stats']['type'] == 'container': for item_id in entity['inventory']['containers'][entity['_id']]: _item = entities.get_entity(item_id) disown(_item) del entity['inventory']['containers'][entity['_id']] if entity['stats']['in_container']: _owner['inventory']['containers'][ entity['stats']['in_container']]['items'].remove(entity['_id']) _owner['inventory']['containers'][entity['stats']['in_container']][ 'weight'] -= entity['stats']['weight'] entity['stats']['in_container'] = None _owner['inventory']['items'].remove(entity['_id']) entity['stats']['owner'] = None
def handle_keyboard_input(): if controls.get_input_char_pressed('\t'): if settings.TICK_MODE == 'strategy': if ui_panel.ACTIVE_MENU: ui_panel.close() else: ui_panel.show_inventory(entity) else: _x, _y = movement.get_position(entity) camera.set_pos(_x - constants.MAP_VIEW_WIDTH/2, _y - constants.MAP_VIEW_HEIGHT/2) if controls.get_input_char_pressed('O'): settings.toggle_show_node_grid() elif controls.get_input_char_pressed('o'): settings.toggle_observer_mode() if controls.get_input_char_pressed('d'): _mx, _my = ui_cursor.get_map_position() for entity_id in entities.get_entity_group('life'): _entity = entities.get_entity(entity_id) if not numbers.distance((_mx, _my), movement.get_position(_entity)): _x, _y = ui_cursor.get_screen_position() _menu = ui_menu.create(_x, _y, title='Debug') ui_menu.add_selectable(_menu, 'Show Metas', lambda: _show_metas(_entity)) ui_menu.add_selectable(_menu, 'Kill', lambda: entities.trigger_event(_entity, 'kill')) ui_menu.add_selectable(_menu, 'Overwatch', lambda: ai_debugger.register(_entity)) break if controls.get_input_char_pressed('l'): _x, _y = ui_cursor.get_screen_position() _mx, _my = ui_cursor.get_map_position() _weight = zones.get_active_weight_map()[_my, _mx] _menu = ui_menu.create(_x, _y, title='Tile Info') ui_menu.add_selectable(_menu, 'Warp', lambda: entities.trigger_event(entity, 'set_position', x=_mx, y=_my)) ui_menu.add_selectable(_menu, 'Light', lambda: effects.light(_mx, _my, 15, r=random.uniform(1.0, 1.5), g=random.uniform(1.0, 1.5), light_map='static_lighting')) ui_menu.add_selectable(_menu, 'Weight: %s' % _weight, lambda: _)
def _shoot_weapon(entity, weapon_id, target_id): _weapon = entities.get_entity(weapon_id) _x, _y = movement.get_position( entities.get_entity(_weapon['stats']['owner'])) if not target_id in entities.ENTITIES: logging.warning('Target deleted during shooting.') return _tx, _ty = movement.get_position(entities.get_entity(target_id)) _direction = numbers.direction_to((_x, _y), (_tx, _ty)) effects.muzzle_flash(_x, _y, _direction) entities.trigger_event(_weapon, 'flag_sub', flag='ammo', value=1) entities.trigger_event(entity, 'create_noise', volume=80, direction=numbers.direction_to((_x, _y), (_tx, _ty)), text='BAM', callback=lambda t, x, y: entities.trigger_event( t, 'update_target_memory', target_id=entity['_id'], key='last_seen_at', value=[x, y]), context_callback=lambda x, y: ui_dialog.create( x, y, 'Gunshot (Unknown)', title='Noise')) entity['stats']['action_points'] -= stats.get_shoot_cost(entity, weapon_id) entities.trigger_event(entity, 'get_accuracy') _accuracy = stats.get_accuracy(entity, weapon_id) _damage = flags.get_flag(_weapon, 'damage') effects.light(_x, _y, random.randint(3, 5), r=1.5, g=1.5, b=0) if _weapon['stats']['kind'] == 'explosive': items.explosive(entity, _x, _y, _tx, _ty, 4, _accuracy, _damage) else: items.bullet(entity, _x, _y, _tx, _ty, 1, _accuracy, _damage)
def find_cover(entity): _squad = entities.get_entity(ai_factions.FACTIONS[entity['ai']['faction']]['squads'][entity['ai']['squad']]) _cover_position = ai_squad_director.get_cover_position(_squad, entity['_id']) if not _cover_position or not numbers.distance(movement.get_position(entity), _cover_position): entities.trigger_event(entity, 'finish_turn') return movement.walk_to_position(entity, _cover_position[0], _cover_position[1], zones.get_active_astar_map(), zones.get_active_weight_map())
def frag_grenade_explode(entity): _x, _y = movement.get_position(entity) _damage = entity['damage'] _size = 3 * int(round((_damage * .01))) effects.explosion(_x, _y, _size) for entity_id in entities.get_entity_group('life'): _entity = entities.get_entity(entity_id) _distance = numbers.distance((_x, _y), movement.get_position(_entity)) if _distance - 1 > _size or not life.can_see_position( _entity, (_x, _y)): continue entities.trigger_event(_entity, 'hit', projectile=entity, damage_mod=1 - ((_distance - 1) / float(_size)))
def _redraw_first_node(entity, **kargs): _x, _y = movement.get_position(entity) for node_id in entity['node_grid']['path']: _node = entity['node_grid']['nodes'][node_id]['node'] if (_x, _y) in _node['path']: if _node['draw_path']: _node['path'] = _node['path'][_node['path'].index((_x, _y)):] break
def _bullet_tick(entity): _direction = movement.get_direction(entity) entities.trigger_event(entity, 'push_tank', direction=_direction) _x, _y = movement.get_position(entity) _distance = numbers.distance((_x, _y), entity['start_position']) _starting_target_distance = numbers.distance(entity['start_position'], entity['end_position']) if _distance > _starting_target_distance + (12 - (entity['speed'] * 2)): entities.delete_entity(entity)
def _locate_npc_message(goal, member_id): _target_id = goal['target_id'] _member = entities.get_entity(member_id) _mission = entities.get_entity(goal['mission_id']) if not _target_id in _member['ai']['life_memory'] or not _member['ai'][ 'life_memory'][_target_id]['last_seen_at']: goal['message'] = 'Gather location info on target.' return if _member['ai']['life_memory'][_target_id]['is_dead']: goal['message'] = 'Confirmed: Target is dead.' entities.trigger_event(_member, 'complete_goal', mission_id=goal['mission_id'], goal_id=goal['_id']) elif _member['ai']['life_memory'][_target_id]['can_see']: goal['message'] = 'Target in line of sight.' entities.trigger_event(_member, 'complete_goal', mission_id=goal['mission_id'], goal_id=goal['_id']) elif _member['ai']['life_memory'][_target_id]['last_seen_at']: _direction = numbers.direction_to( movement.get_position(_member), _member['ai']['life_memory'][_target_id]['last_seen_at']) _distance = numbers.distance( movement.get_position(_member), _member['ai']['life_memory'][_target_id]['last_seen_at']) _real_direction = conversions.get_real_direction(_direction) _real_distance = conversions.get_real_distance(_distance) goal['message'] = 'Target last seen %s meters to the %s' % ( _real_distance, _real_direction) _member['ai']['life_memory'][_target_id]['mission_related'] = True
def check_for_collisions(entity): _x, _y = movement.get_position(entity) if _x < 0 or _x >= zones.get_active_size()[0]-1 or _y < 0 or _y >= zones.get_active_size()[1]-1: entities.delete_entity(entity) return if (_x, _y) in zones.get_active_solids(entity): entities.trigger_event(entity, 'collision_with_solid') return for entity_id in entities.get_entity_group('life'): if entity_id == entity['owner']: continue if movement.get_position(entity) == movement.get_position_via_id(entity_id): entities.trigger_event(entity, 'collision_with_entity', target_id=entity_id) return
def find_push_position(entity): _squad = entities.get_entity(ai_factions.FACTIONS[entity['ai']['faction']]['squads'][entity['ai']['squad']]) _x, _y = movement.get_position(entity) _push_position = ai_squad_director.get_push_position(_squad, entity['_id']) if not _push_position: return #if not numbers.distance((_x, _y), _push_position) and not entity['ai']['visible_targets']: # entity['ai']['meta']['has_lost_target'] = True movement.walk_to_position(entity, _push_position[0], _push_position[1], zones.get_active_astar_map(), zones.get_active_weight_map())
def draw(): _entity = entities.get_entity(HAS_FOCUS) _x, _y = movement.get_position(_entity) _char = tile.get_char(_entity) for y in range(12): display.write_char('ui', 4, 4 + y + 1, ' ', back_color=(20, 20, 20)) display.write_char('ui', 4 + 12, 4 + y, ' ', back_color=(40, 40, 40)) display.write_char('ui', 4 + y, 4, ' ', back_color=(20, 20, 20)) display.write_char('ui', 4 + y + 1, 4 + 12, ' ', back_color=(40, 40, 40)) display.blit_surface_viewport('tiles', _x-5, _y-5, 11, 11, dx=5, dy=5) display.write_char('ui', 10, 10, _char, fore_color=_entity['tile']['fore_color'])
def _shoot_weapon(entity, weapon_id, target_id): _weapon = entities.get_entity(weapon_id) _x, _y = movement.get_position(entities.get_entity(_weapon['stats']['owner'])) if not target_id in entities.ENTITIES: logging.warning('Target deleted during shooting.') return _tx, _ty = movement.get_position(entities.get_entity(target_id)) _direction = numbers.direction_to((_x, _y), (_tx, _ty)) effects.muzzle_flash(_x, _y, _direction) entities.trigger_event(_weapon, 'flag_sub', flag='ammo', value=1) entities.trigger_event(entity, 'create_noise', volume=80, direction=numbers.direction_to((_x, _y), (_tx, _ty)), text='BAM', callback=lambda t, x, y: entities.trigger_event(t, 'update_target_memory', target_id=entity['_id'], key='last_seen_at', value=[x, y]), context_callback=lambda x, y: ui_dialog.create(x, y, 'Gunshot (Unknown)', title='Noise')) entity['stats']['action_points'] -= stats.get_shoot_cost(entity, weapon_id) entities.trigger_event(entity, 'get_accuracy') _accuracy = stats.get_accuracy(entity, weapon_id) _damage = flags.get_flag(_weapon, 'damage') effects.light(_x, _y, random.randint(3, 5), r=1.5, g=1.5, b=0) if _weapon['stats']['kind'] == 'explosive': items.explosive(entity, _x, _y, _tx, _ty, 4, _accuracy, _damage) else: items.bullet(entity, _x, _y, _tx, _ty, 1, _accuracy, _damage)
def _get_item(entity, item_id, hold=False, weight=None): _item = entities.get_entity(item_id) _x, _y = movement.get_position(_item) _distance = numbers.distance(movement.get_position(entity), (_x, _y)) if weight: ai.set_meta_weight(entity, weight, 10 * numbers.clip(_distance / 30.0, 0, 1)) if _distance: movement.walk_to_position(entity, _x, _y, zones.get_active_astar_map(), zones.get_active_weight_map(), smp=True) else: if hold: life.get_and_hold_item(entity, item_id) else: life.get_and_store_item(entity, item_id)
def create_shoot_menu(entity, target_id): _tx, _ty = movement.get_position_via_id(target_id) _weapon = entities.get_entity(items.get_items_in_holder(entity, 'weapon')[0]) _menu = ui_menu.create(_tx-camera.X+2, _ty-camera.Y-4, title='Shoot') _accuracy = stats.get_accuracy(entity, _weapon['_id']) _x, _y = movement.get_position(entity) _direction = numbers.direction_to((_x, _y), (_tx, _ty)) _final_direction = _direction + (_accuracy * numbers.distance((_x, _y), (_tx, _ty))) _spray_accuracy = (100 * (_direction / float(_final_direction))) entities.trigger_event(_weapon, 'get_actions', menu=_menu) ui_menu.add_selectable(_menu, 'Spray (Acc: %.2d)' % _spray_accuracy, lambda: entities.trigger_event(entity, 'shoot', target_id=target_id) and settings.set_tick_mode('normal')) ui_menu.add_selectable(_menu, 'Snipe (Acc: %s)' % _accuracy, lambda: _)
def handle_keyboard_input(): global SELECTED_SQUAD_MEMBER, WALK_PATH, WALK_DEST #TODO: Check for multiple movement changes at this location if not is_squad_member_selected(): return _entity = get_selected_squad_member() _x, _y = movement.get_position(_entity) if timers.has_timer_with_name(_entity, 'passout'): return if controls.get_input_char_pressed('z'): entities.trigger_event(_entity, 'set_motion', motion='crawl') settings.set_tick_mode('normal') elif controls.get_input_char_pressed('x'): entities.trigger_event(_entity, 'set_motion', motion='crouch') settings.set_tick_mode('normal') elif controls.get_input_char_pressed('c'): entities.trigger_event(_entity, 'set_motion', motion='stand') settings.set_tick_mode('normal') elif controls.get_input_char_pressed(' '): _entity['stats']['action_points'] = 0 SELECTED_SQUAD_MEMBER = None WALK_DEST = None WALK_PATH = [] _broken = False for squad_id in entities.get_entity_group('squads'): _squad = entities.get_entity(squad_id) if not _squad['faction'] == 'Rogues': continue for entity_id in _squad['members']: _entity = entities.get_entity(entity_id) if _entity['stats']['action_points'] > 0: _broken = True break if _broken: break else: settings.set_tick_mode('normal')
def draw_long_range_life(): _camera_x, _camera_y = camera.X, camera.Y _width = display.get_surface('life')['width'] _height = display.get_surface('life')['height'] _draw_life_targets = set() if settings.OBSERVER_MODE: _draw_life = entities.get_entity_group('life') else: _draw_life = set() for squad_id in entities.get_entity_group('squads'): _squad = entities.get_entity(squad_id) if not _squad['faction'] == 'Rogues': continue for member_id in _squad['members']: _member = entities.get_entity(member_id) _draw_life.add(member_id) _draw_life.update([i for i in _member['ai']['life_memory'] if _member['ai']['life_memory'][i]['can_see'] and i in entities.ENTITIES]) _draw_life_targets.update([i for i in _member['ai']['life_memory'] if _member['ai']['life_memory'][i]['can_see'] and _member['ai']['life_memory'][i]['is_target'] and i in entities.ENTITIES]) _draw_life = list(_draw_life) for entity_id in _draw_life: _entity = entities.get_entity(entity_id) _x, _y = movement.get_position(_entity) _x -= _camera_x _y -= _camera_y if _x < 0 or _y < 0 or _x >= _width or _y >= _height: _x = numbers.clip(_x, 0, _width-1) _y = numbers.clip(_y, 0, _height-1) else: continue if time.time() % 1 >= .5: _char = 'X' else: _char = 'O' if entity_id in _draw_life_targets: _fore_color = (255, 0, 0) _back_color = (100, 0, 0) else: _fore_color = (255, 255, 255) _back_color = (100, 100, 100) display.write_string('ui', _x, _y, _char, fore_color=_fore_color, back_color=_back_color)
def _blood_splatter_push(entity): _x, _y = movement.get_position(entity) _direction = movement.get_direction(entity) + random.randint(-25, 25) _v_x, _v_y = numbers.velocity(_direction, random.uniform(.55, .75)) if not int(round(_x + _v_x)) == int(round(_x)) or not int(round(_y + _v_y)) == int(round(_y)): blood(_x + _v_x, _y + _v_y) _x += _v_x _y += _v_y entities.trigger_event(entity, 'set_direction', direction=_direction) entities.trigger_event(entity, 'set_position', x=_x, y=_y)
def find_cover(entity): _squad = entities.get_entity(ai_factions.FACTIONS[entity['ai']['faction']] ['squads'][entity['ai']['squad']]) _cover_position = ai_squad_director.get_cover_position( _squad, entity['_id']) if not _cover_position or not numbers.distance( movement.get_position(entity), _cover_position): entities.trigger_event(entity, 'finish_turn') return movement.walk_to_position(entity, _cover_position[0], _cover_position[1], zones.get_active_astar_map(), zones.get_active_weight_map())
def _muzzle_flash_fade(entity): entity['alpha'] -= 0.07 _x, _y = movement.get_position(entity) _color = list(display.get_color_at('tiles', _x, _y)) _color[0] = numbers.interp_velocity(_color[0], (255, 255, 255), entity['alpha']) _color[1] = numbers.interp_velocity(_color[1], (255, 255, 255), entity['alpha']) for c in range(len(_color)): for i in range(len(_color)): _color[c][i] = int((round(_color[c][i]))) entities.trigger_event(entity, 'set_fore_color', color=_color[0]) entities.trigger_event(entity, 'set_back_color', color=_color[1])
def find_push_position(entity): _squad = entities.get_entity(ai_factions.FACTIONS[entity['ai']['faction']] ['squads'][entity['ai']['squad']]) _x, _y = movement.get_position(entity) _push_position = ai_squad_director.get_push_position(_squad, entity['_id']) if not _push_position: return #if not numbers.distance((_x, _y), _push_position) and not entity['ai']['visible_targets']: # entity['ai']['meta']['has_lost_target'] = True movement.walk_to_position(entity, _push_position[0], _push_position[1], zones.get_active_astar_map(), zones.get_active_weight_map())
def draw_life_labels(): _camera_x, _camera_y = camera.X, camera.Y _width = display.get_surface('life')['width'] _height = display.get_surface('life')['height'] if settings.OBSERVER_MODE: _draw_life = entities.get_entity_group('life') else: _draw_life = [ i for i in PLAYER['ai']['life_memory'] if PLAYER['ai']['life_memory'][i]['can_see'] ] if PLAYER['_id'] in entities.ENTITIES: _draw_life.append(PLAYER['_id']) for entity_id in _draw_life: _entity = entities.get_entity(entity_id) _x, _y = movement.get_position(_entity) _x -= _camera_x _y -= _camera_y if _x < 0 or _y < 0 or _x >= _width or _y >= _height: continue _back_color = None if settings.OBSERVER_MODE: _label = _entity['ai']['current_action'] else: _label = life.get_status_string(_entity) if not PLAYER['_id'] == entity_id and PLAYER['ai']['life_memory'][ entity_id]['mission_related'] and time.time() % 1 >= .5: _back_color = (200, 0, 0) _render_x = numbers.clip(_x - len(_label) / 2, 0, _width - len(_label)) _render_y = numbers.clip(_y - 2, 0, _height) if _render_y == _y: _render_y += 2 display.write_string('ui', _render_x, _render_y, _label, back_color=_back_color)
def draw_squads(selected_squad=None): for entity_id in entities.get_entity_group("squads"): _squad = entities.get_entity(entity_id) if _squad["faction"] == "Terrorists": continue _x, _y = movement.get_position(_squad) _r_x = (_x * constants.MAP_CELL_SPACE) + constants.MAP_CELL_SPACE / 2 _r_y = (_y * constants.MAP_CELL_SPACE) + constants.MAP_CELL_SPACE / 2 _fore_color = (200, 200, 200) if selected_squad == entity_id: if time.time() % 1 >= 0.5: _fore_color = (100, 150, 100) display.write_char("map_squads", _r_x, _r_y, "S", fore_color=_fore_color)
def find_melee_position(entity): _target = entity['ai']['nearest_target'] _x, _y = entity['ai']['life_memory'][_target]['last_seen_at'] _closest_pos = {'pos': None, 'distance': 0} _solids = zones.get_active_solids(entity, ignore_entities=[_target]) for x, y in [(_x-1, _y), (_x+1, _y), (_x, _y-1), (_x, _y+1), (_x-1, _y-1), (_x+1, _y-1), (_x-1, _y+1), (_x+1, _y+1)]: if (x, y) in _solids: continue _distance = numbers.distance(movement.get_position(entity), (x, y)) if not _closest_pos['pos'] or _distance < _closest_pos['distance']: _closest_pos['distance'] = _distance _closest_pos['pos'] = (x, y) movement.walk_to_position(entity, _closest_pos['pos'][0], _closest_pos['pos'][1], zones.get_active_astar_map(), zones.get_active_weight_map())
def create_shoot_menu(entity, target_id): _tx, _ty = movement.get_position_via_id(target_id) _weapon = entities.get_entity( items.get_items_in_holder(entity, 'weapon')[0]) _menu = ui_menu.create(_tx - camera.X + 2, _ty - camera.Y - 4, title='Shoot') _accuracy = stats.get_accuracy(entity, _weapon['_id']) _x, _y = movement.get_position(entity) _direction = numbers.direction_to((_x, _y), (_tx, _ty)) _final_direction = _direction + (_accuracy * numbers.distance((_x, _y), (_tx, _ty))) _spray_accuracy = (100 * (_direction / float(_final_direction))) entities.trigger_event(_weapon, 'get_actions', menu=_menu) ui_menu.add_selectable( _menu, 'Spray (Acc: %.2d)' % _spray_accuracy, lambda: entities.trigger_event(entity, 'shoot', target_id=target_id ) and settings.set_tick_mode('normal')) ui_menu.add_selectable(_menu, 'Snipe (Acc: %s)' % _accuracy, lambda: _)