Add a script to reclassify 'individual choice' weapons based on unit skill.
							parent
							
								
									48da06ec37
								
							
						
					
					
						commit
						62cde96724
					
				| @ -0,0 +1,154 @@ | ||||
| -- Rewrite individual choice weapons into specific types. | ||||
| 
 | ||||
| local utils = require 'utils' | ||||
| local dlg = require 'gui.dialogs' | ||||
| 
 | ||||
| local defs = df.global.world.raws.itemdefs | ||||
| local entity = df.global.ui.main.fortress_entity | ||||
| local tasks = df.global.ui.tasks | ||||
| local equipment = df.global.ui.equipment | ||||
| 
 | ||||
| function find_best_weapon(unit,mode) | ||||
|     local best = nil | ||||
|     local skill = nil | ||||
|     local skill_level = nil | ||||
|     local count = 0 | ||||
|     local function try(id,iskill) | ||||
|         local slevel = dfhack.units.getNominalSkill(unit,iskill) | ||||
|         -- Choose most skill | ||||
|         if (skill ~= nil and slevel > skill_level) | ||||
|         or (skill == nil and slevel > 0) then | ||||
|             best,skill,skill_level,count = id,iskill,slevel,0 | ||||
|         end | ||||
|         -- Then most produced within same skill | ||||
|         if skill == iskill then | ||||
|             local cnt = tasks.created_weapons[id] | ||||
|             if cnt > count then | ||||
|                 best,count = id,cnt | ||||
|             end | ||||
|         end | ||||
|     end | ||||
|     for _,id in ipairs(entity.resources.weapon_type) do | ||||
|         local def = defs.weapons[id] | ||||
|         if def.skill_ranged >= 0 then | ||||
|             if mode == nil or mode == 'ranged' then | ||||
|                 try(id, def.skill_ranged) | ||||
|             end | ||||
|         else | ||||
|             if mode == nil or mode == 'melee' then | ||||
|                 try(id, def.skill_melee) | ||||
|             end | ||||
|         end | ||||
|     end | ||||
|     return best | ||||
| end | ||||
| 
 | ||||
| function unassign_wrong_items(unit,position,spec,subtype) | ||||
|     for i=#spec.assigned-1,0,-1 do | ||||
|         local id = spec.assigned[i] | ||||
|         local item = df.item.find(id) | ||||
| 
 | ||||
|         if item.subtype.subtype ~= subtype then | ||||
|             spec.assigned:erase(i) | ||||
| 
 | ||||
|             -- TODO: somewhat unexplored area; maybe missing some steps | ||||
|             utils.erase_sorted(position.assigned_items,id) | ||||
|             if utils.erase_sorted(equipment.items_assigned.WEAPON,item,'id') then | ||||
|                 utils.insert_sorted(equipment.items_unassigned.WEAPON,item,'id') | ||||
|             end | ||||
|             equipment.update.weapon = true | ||||
|             unit.military.pickup_flags.update = true | ||||
|         end | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| local count = 0 | ||||
| 
 | ||||
| function adjust_uniform_spec(unit,position,spec,force) | ||||
|     if not unit then return end | ||||
|     local best | ||||
|     if spec.indiv_choice.melee then | ||||
|         best = find_best_weapon(unit, 'melee') | ||||
|     elseif spec.indiv_choice.ranged then | ||||
|         best = find_best_weapon(unit, 'ranged') | ||||
|     elseif spec.indiv_choice.any or force then | ||||
|         best = find_best_weapon(unit, nil) | ||||
|     end | ||||
|     if best then | ||||
|         count = count + 1 | ||||
|         spec.item_filter.item_subtype = best | ||||
|         spec.indiv_choice.any = false | ||||
|         spec.indiv_choice.melee = false | ||||
|         spec.indiv_choice.ranged = false | ||||
|         unassign_wrong_items(unit, position, spec, best) | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| function adjust_position(unit,position,force) | ||||
|     if not unit then | ||||
|         local fig = df.historical_figure.find(position.occupant) | ||||
|         if not fig then return end | ||||
|         unit = df.unit.find(fig.unit_id) | ||||
|     end | ||||
| 
 | ||||
|     for _,v in ipairs(position.uniform.weapon) do | ||||
|         adjust_uniform_spec(unit, position, v, force) | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| function adjust_squad(squad, force) | ||||
|     for _,pos in ipairs(squad.positions) do | ||||
|         adjust_position(nil, pos, force) | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| local args = {...} | ||||
| local vs = dfhack.gui.getCurViewscreen() | ||||
| local vstype = df.viewscreen_layer_militaryst | ||||
| if not vstype:is_instance(vs) then | ||||
|     qerror('Call this from the military screen') | ||||
| end | ||||
| 
 | ||||
| if vs.page == vstype.T_page.Equip | ||||
| and vs.equip.mode == vstype.T_equip.T_mode.Customize then | ||||
|     local slist = vs.layer_objects[0] | ||||
|     local squad = vs.equip.squads[slist:getListCursor()] | ||||
| 
 | ||||
|     if slist.active then | ||||
|         print('Adjusting squad.') | ||||
|         adjust_squad(squad) | ||||
|     else | ||||
|         local plist = vs.layer_objects[1] | ||||
|         local pidx = plist:getListCursor() | ||||
|         local pos = squad.positions[pidx] | ||||
|         local unit = vs.equip.units[pidx] | ||||
| 
 | ||||
|         if plist.active then | ||||
|             print('Adjusting position.') | ||||
|             adjust_position(unit, pos) | ||||
|         elseif unit and vs.equip.edit_mode < 0 then | ||||
|             local wlist = vs.layer_objects[2] | ||||
|             local idx = wlist:getListCursor() | ||||
|             local cat = vs.equip.assigned.category[idx] | ||||
| 
 | ||||
|             if wlist.active and cat == df.uniform_category.weapon then | ||||
|                 print('Adjusting spec.') | ||||
|                 adjust_uniform_spec(unit, pos, vs.equip.assigned.spec[idx], true) | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| else | ||||
|     qerror('Call this from the Equip page of military screen') | ||||
| end | ||||
| 
 | ||||
| if count > 1 then | ||||
|     dlg.showMessage( | ||||
|         'Choose Weapons', | ||||
|         'Updated '..count..' uniform entries.', COLOR_GREEN | ||||
|     ) | ||||
| elseif count == 0 then | ||||
|     dlg.showMessage( | ||||
|         'Choose Weapons', | ||||
|         'Did not find any entries to update.', COLOR_YELLOW | ||||
|     ) | ||||
| end | ||||
		Loading…
	
		Reference in New Issue