def _food_cokenut(ent): def func(ent, eater): rog.poison(eater) rog.world().add_component(ent, cmp.Edible( func=func, sat=FOOD_MORSEL, taste=TASTE_BITTER )) rog.world().add_component(ent, cmp.Ingredient(ING_COKENUT))
def remove_all(self, ent): # TODO: finish this for status, component in cmp.STATUSES.items(): if not rog.world().has_component(ent, component): continue #attribute modifiers #auxiliary effects #message rog.world().remove_component(ent, component)
def _incendiary(tt): def deathFunc(ent): entn = rog.get(ent, cmp.Name) pos = rog.get(ent, cmp.Position) rog.set_fire(pos.x, pos.y) radius = 1 rog.explosion("{}{}".format(entn.title,entn.name), pos.x,pos.y, radius) rog.world().add_component(tt, cmp.DeathFunction(deathFunc))
def talk_smalltalk(ent:int, personality:int, disposition:int, value=0, style=0) -> tuple: ttype = TALK_SMALLTALK reaction=_get_reaction(ent, ttype, personality, disposition, style=style) success = (reaction > 0) _change_disposition(ent, reaction, PERSUASION[ttype][2]) if rog.world().has_component(ent, cmp.SmallTalked): annoy(ent, 40) rog.world().add_component(ent, cmp.SmallTalked()) return _talk(ent, success, ttype, personality, disposition, 300, padding=0.3)
def add_entity_heat_source(cls, ent): pos = rog.world().component_for_entity(ent, cmp.Position) temp = rog.world().component_for_entity(ent, cmp.Meters).temp mass = rog.getms(ent, "mass") sourceValue = cls.calc_source_heat(temp, mass) if ent in cls.entsources: # remove current heat source data for entity cls.heat_sources[pos.y][pos.x] -= cls.entsources[ent] cls.heat_sources[pos.y][pos.x] += sourceValue cls.entsources[ent] = sourceValue
def add_thing(self, ent): #try to add a thing to the grid, return success pos = rog.world().component_for_entity(ent, cmp.Position) x = pos.x; y = pos.y; if self.monat(x,y): if rog.world().has_component(ent, Creature): return False #only one creature per tile is allowed else: #insert thing right below the creature self.grid_things[x][y][-1:0] = [ent] return True else: #insert thing at top of the list self.grid_things[x][y].append(ent) return True
def remove_thing(self, ent): ''' try to remove an entity from the grid, return success/failure ''' if not rog.world().has_component(ent, cmp.Position): return False pos = rog.world().component_for_entity(ent, cmp.Position) tile = self.grid_things[pos.x][pos.y] if ent in tile: tile.remove(ent) return True ## print('''Error: failed to remove entity {} from grid. ##Reason: entity not in grid.'''.format(ent)) return False #thing was not in the grid.
def remove(self, ent, component): if not rog.world().has_component(ent, component): return False status_str = "" #attribute modifiers, aux. effects, message (based on status type) if component is cmp.StatusHaste: status_str = "'s movements slow" elif component is cmp.StatusSlow: status_str = "'s movements speed up" #if status_str: #"{}{}{}".format(TITLES[name.title], name.name, status_str) rog.world().remove_component(ent, component) return True
def queue(cls, ent, totalAP, func, data=None, cancelfunc=None): ''' queue a new job Parameters: ent : entity performing the job totalAP : total Action Points required to complete the job func : the function that will be executed when the job is completed data : additional data needed by the job to be completed e.g. the item entity being crafted ''' rog.world().add_component( ent, cmp.DelayedAction(totalAP, func, data=data, cancelfunc=cancelfunc))
def _select_talent(): menu={} for k,v in sorted(SKILLS.items(), key=lambda x: x[1][1].lower()): menu[v[1]] = k menu["<cancel>"] = -1 choice=rog.menu( "In which skill are you talented?", 0,0, menu.keys(), autoItemize=True ) if choice!=-1: selected = menu[choice] rog.world().add_component(Chargen.pc, cmp.Talented( {selected: TALENTED_EXPMOD} )) return True return False
def create_stuff(ID, x, y): name,typ,mat,val,fgcol,hp,kg,solid,push,script = STUFF[ID] world = rog.world() if fgcol == "random": fgcol = random.choice(list(COL.keys())) ## tt = thing.Thing(x,y, _type=typ,name=name,color=COL[fgcol]) ## tt.mass = kg ## tt.material=mat ## if lo: _hp(tt, lo) ## tt.isSolid = solid ## if push: rog.make(tt, CANPUSH) ## #_applyResistancesFromMaterial(tt, mat) ## return tt ent = world.create_entity( cmp.Name(name), cmp.Position(x,y), cmp.Draw(typ, fgcol=fgcol), cmp.Form(mass=kg, mat=mat, val=val), cmp.BasicStats(hp=hp,mp=hp), ) if solid: rog.make(ent, ISSOLID) if push: rog.add_component(ent, cmp.Pushable()) script(ent) return ent
def _dosimeter(tt): #use function two options: 1) toggles on/off. 2) displays a reading only when you use it. world=rog.world() def diesInWaterFunc(ent): world.delete_entity(ent) def funcDeath(ent): entn=world.component_for_entity(ent, cmp.Name) pos=world.component_for_entity(ent, cmp.Position) rog.explosion(entn.name, pos.x,pos.y, 1) def funcUsePC(self, ent): pos=world.component_for_entity(ent, cmp.Position) reading = rog.radsat(pos.x,pos.y) rog.msg("The geiger counter reads '{} RADS'".format(reading)) #could do, instead: # use turns it on, activates an observer. # updates when rad damage received by player. Adds rad value to dosimeter # when you use again, you can either read it or turn it off. rog.spendAP(ent, NRG_USE) def funcUseNPC(self, ent): rog.spendAP(ent, NRG_USE) pos=world.component_for_entity(ent, cmp.Position) rog.event_sight(pos.x,pos.y,"{t}{n} looks at a geiger counter.") statMods={cmp.CombatStats : {"rng":3,"atk":2,"dmg":1,},} world.add_component(ent, cmp.Usable(funcUsePC,funcUseNPC)) world.add_component(ent, cmp.ReactsWithWater(diesInWaterFunc)) world.add_component(ent, cmp.CanEquipInMainhandSlot(statMods)) world.add_component(ent, cmp.DeathFunction(funcDeath))
def _gobble(self, ent): world = rog.world() pos = world.component_for_entity(ent, cmp.Position) stats = world.component_for_entity(ent, cmp.BasicStats) isCreature = world.has_component(ent, cmp.Creature) #print("gobbling object {} at {},{}".format(obj.name,obj.x,obj.y)) food = 0 if stats.material == MAT_WOOD: food = 10 if dice.roll(6) == 1: #chance to make popping fire sound self.soundsList.update({( pos.x, pos.y, ): SND_FIRE}) elif stats.material == MAT_FLESH: food = 2 if not isCreature: #corpses burn better than alive people food = 3 elif obj.material == MAT_VEGGIE: food = 3 elif obj.material == MAT_SAWDUST: food = 50 elif obj.material == MAT_GUNPOWDER: food = 100 elif obj.material == MAT_PAPER: food = 10 elif obj.material == MAT_CLOTH: food = 10 elif obj.material == MAT_LEATHER: food = 1 elif obj.material == MAT_FUNGUS: food = 1 elif obj.material == MAT_PLASTIC: food = 1 return food
def tick(obj): world = rog.world() if not world.has_component(ent, cmp.AI): return aiFunc = world.component_for_entity(ent, cmp.AI).func actor = world.component_for_entity(ent, cmp.Actor) while actor.ap > 0: aiFunc(obj)
def annoy(ent:int, amt:int): # buildup for Annoyed Status world = rog.world() if not world.has_component(ent, cmp.GetsAnnoyed): return # if I love you, annoyance amount is reduced; hate increases it rat = get_disp_ratio(ent) if rat <= 0.1: amt = amt * 3 elif rat <= 0.2: amt = amt * 2 elif rat >= 0.4: amt = amt * 0.5 elif rat >= 0.6: amt = amt * 0.25 elif rat >= 0.8: amt = amt * 0.1 amt = _apply_compatibility_modifier_pseudostatus(ent, amt) # add annoyance, set annoyed status if applicable dice_size = rog.around(amt * res_annoyance(ent)) compo = world.component_for_entity(ent, cmp.GetsAnnoyed) compo.annoyance += dice.roll(dice_size) if compo.annoyance >= MAX_ANNOYANCE: compo.annoyance = 0 print("ANNOYED!") rog.set_status(ent, cmp.StatusAnnoyed, target=rog.pc())
def run(self): super(Manager_SoundsHeard, self).run() pc = rog.pc() atLeastOneMsg = False text = "You hear " skills = rog.world().component_for_entity(pc, cmp.Skills) for k, v in self.sounds.items(): vol, lis = v if not vol: continue if vol > VOLUME_DEAFEN: rog.set_status(pc, DEAF) #super hearing ## if SKL_SUPERHEARING in skills.skills: ## volTxt=self.get_volume_name(vol) ## dirStr=DIRECTIONS_TERSE[k] ## if not dirStr == "self": ## text += "<{d}>".format(d=dirStr) ## text += "({v}) ".format(v=volTxt) #combine strings with commas for strng in lis: text += "{s}, ".format(s=strng) #terminate with a period text = text[:-2] + "." atLeastOneMsg = True if atLeastOneMsg: rog.msg(text) self.init_sounds()
def create_targetList(self, ent, **kwargs): pos = rog.world().component_for_entity(ent, cmp.Position) sight = rog.getms(ent, 'sight') radius = sight interesting = [] for mon, ( tgt, monpos, ) in rog.world().get_components(cmp.Targetable, cmp.Position): dist = ((pos.x - monpos.x)**2 + (pos.y - monpos.y)**2)**0.5 if dist < radius: interesting.append(( mon, dist, )) self.targets = sorted(interesting, key=lambda x: x[1])
def _draw_silhouettes(self, pc, tx,ty, ent, sight): ''' # extend a line from tile tx,ty to a distant tile # which is in the same direction from the player. # Check for lit tiles, and if we find any along the way, # draw a silhouette for the location of interest. # Basically, if the ent is backlit, you can see # a silhouette. ''' world=rog.world() if not sight: return if not (ent and world.has_component(ent, cmp.Creature)): return pos=world.component_for_entity(ent, cmp.Position) dist=maths.dist(pos.x,pos.y, tx,ty) dx=(tx - pos.x)/dist dy=(ty - pos.y)/dist xdest=tx + int(dx*sight) ydest=ty + int(dy*sight) libtcod.line_init(tx,ty, xdest,ydest) while True: x,y=libtcod.line_step() if x is None: return if maths.dist(pos.x,pos.y, x,y) > sight: return if self.get_blocks_sight(x,y): return if self.get_perceived_light_value(x,y): libtcod.console_put_char(self.con_map_state, tx,ty, "?") return
def greet(ent:int, style=0) -> int: # attempt to init conversation pc=rog.pc() world=rog.world() personality=world.component_for_entity(ent,cmp.Personality).personality dispcompo=world.component_for_entity(ent,cmp.Disposition) # new disposition after dialogue concludes new_disposition = dispcompo.disposition # effective disposition during this dialogue (not the new disposition) ed = dispcompo.disposition + _get_reaction( ent, TALK_GREETING, personality, dispcompo.disposition, style=style, mx=0.5 ) reaction = rog.sign(ed) # just nudge disposition fdisp = ed / MAX_DISPOSITION # roll for speech success speech_bonus = rog.getskill(pc, SKL_PERSUASION) roll=dice.roll(100) + speech_bonus if fdisp < 0.4: roll -= 8/fdisp else: roll += 100*fdisp # cases if roll <= 0: _response(ent, RESPONSE_REJECTION) else: _response(ent, RESPONSE_ACCEPT) return reaction
def givefunc(pc, item): # context-sensitive removal of item from your person rog.remove_equipment(pc, item) if rog.world().has_component(item, cmp.Carried): rog.take(pc, item) # give to NPC rog.give(pc, item)
def _change_disposition(ent, amt, maximum=999999): ## print("ent {} disp change: {}".format(rog.getname(ent), amt)) compo = rog.world().component_for_entity(ent,cmp.Disposition) if ((amt > 0 and compo.disposition < maximum) or amt < 0): compo.disposition += amt compo.disposition = max(0, compo.disposition)
def _draw_what_player_sees(self, pc): world=rog.world() seer=world.component_for_entity(pc, cmp.SenseSight) rang=seer.sight pos=world.component_for_entity(pc, cmp.Position) rend=world.component_for_entity(ent, cmp.Draw) for x in range( max(0, pc.x-rang), min(self.w, pc.x+rang+1) ): for y in range( max(0, pc.y-rang), min(self.h, pc.y+rang+1) ): canSee=False if not rog.in_range(pos.x,pos.y, x,y, rang): continue if not libtcod.map_is_in_fov(seer.fov_map, x,y): continue ent=self.thingat(x, y) if (self.get_light_value(x,y) == 0 and not rog.on(pc,NVISION) ): self._draw_silhouettes(pc, x,y, ent) continue if ent: libtcod.console_put_char( self.con_map_state, x,y, rend.char) libtcod.console_set_char_foreground( self.con_map_state, x,y, rend.color) self._apply_rendered_bgcol(x,y, ent) else: libtcod.console_put_char_ex(self.con_map_state, x,y, self.get_char(x, y), self.get_color(x, y), self.get_bgcolor(x, y))
def cough(ent): world = rog.world() pos = world.component_for_entity(ent, cmp.Position) entn = world.component_for_entity(ent, cmp.Name) wait(ent) rog.event_sound(pos.x,pos.y, SND_COUGH) rog.event_sight(pos.x,pos.y, "{t}{n} hacks up a lung.".format( t=entn.title,n=entn.name))
def inanat(self,x,y): #return inanimate thing at top of the pile at tile ent=self.thingat(x,y) if not ent: return None gridTile=self.grid_things[x][y] if (rog.world().has_component(ent, Creature) and len(gridTile) > 1): ent=gridTile[-2] #thing under the top thing if ent: return ent else: return ent
def _still(ent): world=rog.world() def funcPC(thing, actor): pass def funcNPC(thing, actor): pass world.add_component(ent, cmp.Interactable(funcPC,funcNPC)) world.add_component(ent, cmp.FluidContainer(capacity=100))
def remove_thing(self, ent): pos = rog.world().component_for_entity(ent, cmp.Position) x = pos.x; y = pos.y; grid = self.grid_things[x][y] if ent in grid: grid.remove(ent) return True return False #thing was not in the grid.
def fight(attkr,dfndr,adv=0): ## TODO: when you attack, look at your weapon entity to get: #-material of weapon #-element of weapon #-flags of weapon world = rog.world() cstats = world.component_for_entity(attkr, cmp.CombatStats) dpos = world.component_for_entity(dfndr, cmp.Position) element = ELEM_PHYS #****TEMPORARY!!!! has_component... nrg_cost = round( NRG_ATTACK*AVG_SPD/max(1, cstats.asp) ) cstats.ap -= nrg_cost die=COMBATROLL acc=cstats.atk dv=cstats.dfn hit = False rol = dice.roll(die + acc + adv - dv) - dice.roll(die) if (rol >= 0): # HIT!!! hit = True #type of damage dealt depends on the element attacker is using if element == ELEM_PHYS: #high attack values can pierce armor ## if rol > ATK_BONUS_DMG_CUTOFF: ## pierce = int( (rol - ATK_BONUS_DMG_CUTOFF)/2 ) ## else: ## pierce = 0 armor = dfndr.stats.get('arm') #max(0, dfndr.stats.get('arm') - pierce) dmg = max(0, attkr.stats.get('dmg') - armor) rog.hurt(dfndr, dmg) elif element == ELEM_FIRE: rog.burn(dfndr, dmg) elif element == ELEM_BIO: rog.disease(dfndr, dmg) elif element == ELEM_ELEC: rog.electrify(dfndr, dmg) elif element == ELEM_CHEM: rog.exposure(dfndr, dmg) elif element == ELEM_RADS: rog.irradiate(dfndr, dmg) killed = rog.on(dfndr,DEAD) #...did we kill it? # message = True a=attkr.name; n=dfndr.name; t1=attkr.title; t2=dfndr.title; x='.'; # make a message describing the fight if message: if hit==False: v="misses" elif dmg==0: v="cannot penetrate"; x="'s armor!" elif killed: v="defeats" else: v="hits" rog.event_sight( dfndr.x,dfndr.y, "{t1}{a} {v} {t2}{n}{x}".format(a=a,v=v,n=n,t1=t1,t2=t2,x=x) ) rog.event_sound(dpos.x,dpos.y, SND_FIGHT)
def get_direction(self, pc, coords): xf, yf = coords pos = rog.world().component_for_entity(pc, cmp.Position) if (pos.x == xf and pos.y == yf): return 0, 0 rads = maths.pdir(pos.x, pos.y, xf, yf) dx = round(math.cos(rads)) dy = round(math.sin(rads)) return dx, dy
def _safe(ent): world=rog.world() def funcPC(thing, actor): pass def funcNPC(thing, actor): pass world.add_component(ent, cmp.Interactable(funcPC,funcNPC)) world.add_component(ent, cmp.Inventory(capacity=200)) world.add_component(ent, cmp.Openable(isOpen=False,isLocked=True))
def get_effective_disposition(ent:int, disposition:int): world=rog.world() ret = disposition # charmed bonus if world.has_component(ent, cmp.StatusCharmed): compo = world.component_for_entity(ent, cmp.StatusCharmed) if rog.pc()==world.component_for_entity(ent, cmp.StatusCharmed).entity: ret += compo.quality return rog.around(min(MAX_DISPOSITION, ret))