├── LICENSE ├── README.md └── addons └── gldsrcBSP ├── BSP_Map.tscn ├── DFile.gd ├── baseScene.gd ├── cubemap.shader ├── funcScripts ├── ambient_generic.gd ├── cdaudio.gd ├── decal.gd ├── decal.tscn ├── env_laser.gd ├── func_breakable.gd ├── func_button.gd ├── func_door.gd ├── func_door_rotating.gd ├── func_ladder.gd ├── func_pendulum.gd ├── func_rot_button.gd ├── func_rotating.gd ├── func_track_train.gd ├── func_train.gd ├── light.gd ├── multi_manager.gd ├── trigger.gd ├── trigger_auto.gd ├── trigger_changelevel.gd ├── trigger_push.gd ├── trigger_relay.gd ├── trigger_teleport.gd └── water.gd ├── lightmapAtlas.gd ├── player ├── Crosshair.gd ├── UI.tscn ├── debug │ ├── CanvasLayer.tscn │ └── debug.gd ├── player.gd └── player.tscn ├── plugin.cfg ├── plugin.gd ├── pluginToolbar.tscn └── src ├── BSP_Map.gd ├── bmpLoader.gd ├── entityDataParser.gd ├── imageBuilder.gd ├── levelBuilder.gd ├── mdlLoad.gd └── wavLoad.gd /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 DataPlusProgram 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GodotGoldSrcBSP 2 | 3 | A plugin that allows you to laod GoldSrc BSP files into Godot 4 | 5 | ## Video Demo 6 | [![](https://i.imgur.com/UbihCVB.png)](https://www.youtube.com/watch?v=-gloaTbZxmU) 7 | 8 | ## Installation 9 | Copy the "addons" folder into the root directory of the Godot Project 10 | 11 | Go to Project->Project Settings->Plugins and set the plugins status to "Active" 12 | 13 | ## Usage 14 | 15 | **Note that this isn't finished yet and is only here for testing purposes. Currently it only works by linkng the external GoldSrc game directory and as such can't yet be included into your Godot Project Directory** 16 | 17 | ![](https://i.imgur.com/FINHIjn.png) 18 | 19 | Drag the BSP_Map.tscn file from the addons/gldsrcBSP folder into the scene tree. 20 | 21 | Enter thet path to the bsp in "Path" field and Press "Create Map" 22 | 23 | If you want the map to generate on runtime don't press "Create Map" and it will automatically be created on launch. 24 | 25 | ## Entities 26 | 27 | This plugin supports various but not all entities. 28 | If you want a body to trigger/interact with the entities add it to the "hlTrigger" group. 29 | 30 | 31 | ## Lightmaps 32 | 33 | You can import lightmaps from the BSP file but you will need to set your enviroment to "Clear Color" and up the ambient light. 34 | 35 | ## Real-time lights and global illumination 36 | 37 | As an alternative or as a complement to lightmaps stored in the map file, 38 | you can use real-time lighting and global illumination. Real-time lighting can provide a better 39 | appearance and allows for lights to change during gameplay, 40 | but it's much slower to render compared to lightmaps. 41 | 42 | The resulting MeshInstances are configured to cast double-sided shadows. 43 | This allows real-time lights to cast mostly correct shadows, but peter-panning may still be present due to 44 | faces being hollow. 45 | Tweaking the lights' shadow bias values may help, but it's not always sufficient to hide shadow peter-panning. 46 | If tweaking the lights' shadow bias values doesn't suffice, try adding solid MeshInstances behind hollow walls 47 | manually to act as shadow casters. 48 | 49 | For global illumination, GIProbe can be used as the resulting MeshInstances are set to be used in baked light. 50 | However, BakedLightmap will not work correctly as UV2 isn't generated properly for the generated meshes. 51 | 52 | ## Media 53 | 54 | ![](https://i.imgur.com/STAOPjS.jpg) 55 | ![](https://i.imgur.com/UtKyFi5.png) -------------------------------------------------------------------------------- /addons/gldsrcBSP/BSP_Map.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=9 format=2] 2 | 3 | [ext_resource path="res://addons/gldsrcBSP/src/BSP_Map.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/gldsrcBSP/src/entityDataParser.gd" type="Script" id=2] 5 | [ext_resource path="res://addons/gldsrcBSP/src/levelBuilder.gd" type="Script" id=3] 6 | [ext_resource path="res://addons/gldsrcBSP/src/wavLoad.gd" type="Script" id=4] 7 | [ext_resource path="res://addons/gldsrcBSP/src/imageBuilder.gd" type="Script" id=5] 8 | [ext_resource path="res://addons/gldsrcBSP/src/bmpLoader.gd" type="Script" id=6] 9 | [ext_resource path="res://addons/gldsrcBSP/src/mdlLoad.gd" type="Script" id=7] 10 | [ext_resource path="res://addons/gldsrcBSP/lightmapAtlas.gd" type="Script" id=8] 11 | 12 | [node name="BSP_Map" type="Spatial"] 13 | transform = Transform( 0.05, 0, 0, 0, 0.05, 0, 0, 0, 0.05, 0, 0, 0 ) 14 | script = ExtResource( 1 ) 15 | __meta__ = { 16 | "done": true 17 | } 18 | scaleFactor = 1.0 19 | 20 | [node name="levelBuilder" type="Spatial" parent="."] 21 | script = ExtResource( 3 ) 22 | __meta__ = { 23 | "hidden": true 24 | } 25 | 26 | [node name="entityDataParser" type="Node" parent="."] 27 | script = ExtResource( 2 ) 28 | __meta__ = { 29 | "hidden": true 30 | } 31 | 32 | [node name="waveLoader" type="Node" parent="."] 33 | script = ExtResource( 4 ) 34 | __meta__ = { 35 | "hidden": true 36 | } 37 | 38 | [node name="ImageBuilder" type="Node" parent="."] 39 | script = ExtResource( 5 ) 40 | __meta__ = { 41 | "hidden": true 42 | } 43 | 44 | [node name="bmpLoader" type="Node" parent="."] 45 | script = ExtResource( 6 ) 46 | __meta__ = { 47 | "hidden": true 48 | } 49 | 50 | [node name="mdlLoader" type="Node" parent="."] 51 | script = ExtResource( 7 ) 52 | __meta__ = { 53 | "hidden": true 54 | } 55 | 56 | [node name="lightmapAtlas" type="Node" parent="."] 57 | script = ExtResource( 8 ) 58 | __meta__ = { 59 | "hidden": true 60 | } 61 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/DFile.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | var timings = {} 3 | 4 | 5 | var data 6 | var pos = 0 7 | 8 | func loadFile(path): 9 | var file = File.new() 10 | if file.open(path,File.READ) != 0: 11 | #print("Error opening file:",path) 12 | return false 13 | data = file.get_buffer(file.get_len()) 14 | 15 | file.close() 16 | return true 17 | 18 | 19 | func seek(offset): 20 | pos = offset 21 | 22 | func get_position(): 23 | return pos 24 | 25 | func get_8(): 26 | var ret = data[pos] 27 | pos+=1 28 | return ret 29 | 30 | func bulkByteArr(size): 31 | var ret = data.subarray(pos,pos+size) 32 | pos += size 33 | return ret 34 | 35 | func get_16(): 36 | var ret = data.subarray(pos,pos+1) 37 | pos+=2 38 | 39 | #var spb = StreamPeerBuffer.new() 40 | #spb.data_array = ret 41 | #var single_float = spb.get_16() 42 | 43 | #return single_float 44 | var rety = (ret[1] << 8) + ret[0] 45 | return (ret[1] << 8) + ret[0] 46 | 47 | func get_32u(): 48 | var ret = data.subarray(pos,pos+3) 49 | pos+=4 50 | return (ret[3] << 24) + (ret[2] << 16) + (ret[1] << 8 ) + ret[0] 51 | 52 | 53 | func get_32(): 54 | var ret = data.subarray(pos,pos+3) 55 | var spb = StreamPeerBuffer.new() 56 | spb.data_array = ret 57 | var single_float = spb.get_32() 58 | pos+=4 59 | return single_float 60 | 61 | func get_16u(): 62 | var ret = data.subarray(pos,pos+1) 63 | ret = (ret[1] << 8) + ret[0] 64 | if (ret & 0x8000): 65 | ret -= 0x8000 66 | ret = (-32767 + ret) -1 67 | 68 | pos+=2 69 | return ret 70 | 71 | func get_Vector32(): 72 | var x = get_float32() 73 | var y = get_float32() 74 | var z = get_float32() 75 | return Vector3(x,y,z) 76 | 77 | func get_float32(): 78 | var ret = data.subarray(pos,pos+3) 79 | var spb = StreamPeerBuffer.new() 80 | spb.data_array = ret 81 | var single_float = spb.get_float() 82 | pos+=4 83 | return single_float 84 | 85 | 86 | func get_buffer(size): 87 | var ret = data.subarray(pos,pos+(size-1))#not sure why using -1 here 88 | pos+=size 89 | return ret 90 | 91 | func get_String(length): 92 | var ret = data.subarray(pos,pos+(length-1)).get_string_from_ascii() 93 | 94 | pos+=length 95 | return ret.to_upper() 96 | 97 | #func get_line(): 98 | # return data.get_line() 99 | func get_len(): 100 | return data.size() 101 | 102 | func eof_reached(): 103 | return pos >= data.size() 104 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/baseScene.gd: -------------------------------------------------------------------------------- 1 | extends Spatial 2 | 3 | 4 | func changeMap(strName): 5 | 6 | #$"BSP_Map".queue_free() 7 | var dir : String = $"BSP_Map".path.replace("\\","//") 8 | var listeners = $"BSP_Map".get_signal_connection_list("playerSpawnSignal") 9 | remove_child($"BSP_Map") 10 | var bspMap = load("res://addons/gldsrcBSP/BSP_Map.tscn").instance() 11 | 12 | 13 | 14 | dir = dir.substr(0,dir.find_last("/")) 15 | #var dir = $"BSP_Map".path.find_last("\") 16 | bspMap.path = dir + "/" + strName + ".bsp" 17 | bspMap.name = "BSP_Map" 18 | add_child(bspMap) 19 | 20 | for l in listeners: 21 | bspMap.connect("playerSpawnSignal",l["target"],"setSpawn") 22 | 23 | bspMap.loadBSP() 24 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/cubemap.shader: -------------------------------------------------------------------------------- 1 | shader_type spatial; 2 | render_mode blend_mix, unshaded; 3 | 4 | uniform samplerCube cube_map : hint_albedo; 5 | 6 | void fragment(){ 7 | vec3 dir = (CAMERA_MATRIX * vec4(normalize(VERTEX), 0.0)).xyz; 8 | ALBEDO = texture(cube_map, dir).rgb; 9 | } -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/ambient_generic.gd: -------------------------------------------------------------------------------- 1 | extends AudioStreamPlayer3D 2 | 3 | func toggle(): 4 | if !playing: 5 | play() 6 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/cdaudio.gd: -------------------------------------------------------------------------------- 1 | extends AudioStreamPlayer 2 | 3 | func activate(): 4 | play() 5 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/decal.gd: -------------------------------------------------------------------------------- 1 | extends Sprite3D 2 | 3 | 4 | 5 | var flag = true 6 | var ready = false 7 | var tickWait = 0 8 | func _ready(): 9 | ready = true 10 | get_node("Area/CollisionShape").shape.radius = 0.10 11 | 12 | pass # Replace with function body. 13 | 14 | 15 | func _physics_process(delta): 16 | if tickWait == 3: 17 | checkCasts() 18 | get_node("Area").queue_free() 19 | tickWait+=1 20 | 21 | 22 | 23 | func checkCasts(): 24 | var closest = {"object":null,"distance":INF,"contactNormal":Vector3.ZERO} 25 | var area : KinematicBody= get_node("Area") 26 | var collision = area.move_and_collide(Vector3.ZERO) 27 | if collision!= null: 28 | var collider = collision.collider 29 | if collider.get_node_or_null("face0"): 30 | var face = collider.get_node("face0") 31 | var meta = face.get_meta("normal") 32 | var v1 = Vector3(0,0,1) 33 | var v2 = collision.normal 34 | var ang = acos(v1.dot(v2)) 35 | var rotAxis = v1.cross(v2).normalized() 36 | rotate(rotAxis.normalized(),ang) 37 | translation += collision.normal*0.01 38 | else: 39 | queue_free() 40 | else: 41 | queue_free() 42 | 43 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/decal.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://addons/gldsrcBSP/funcScripts/decal.gd" type="Script" id=1] 4 | 5 | [sub_resource type="SphereShape" id=52] 6 | radius = 0.1 7 | 8 | [node name="Sprite3D" type="Sprite3D"] 9 | script = ExtResource( 1 ) 10 | 11 | [node name="Area" type="KinematicBody" parent="."] 12 | collision_mask = 2 13 | 14 | [node name="CollisionShape" type="CollisionShape" parent="Area"] 15 | shape = SubResource( 52 ) 16 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/env_laser.gd: -------------------------------------------------------------------------------- 1 | extends Sprite3D 2 | 3 | 4 | # Declare member variables here. Examples: 5 | # var a = 2 6 | # var b = "text" 7 | 8 | 9 | # Called when the node enters the scene tree for the first time. 10 | func _ready(): 11 | var target = get_meta("target") 12 | var targetNode = get_tree().get_nodes_in_group(get_meta("target"))[0] 13 | 14 | 15 | # Called every frame. 'delta' is the elapsed time since the previous frame. 16 | #func _process(delta): 17 | # pass 18 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/func_breakable.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | 4 | var targetNodePaths = [] 5 | var targetNodes 6 | var breakSound = null 7 | var unbreakable = false 8 | var targetName = null 9 | var matSound ={ 10 | 0: "debris/bustglass1.wav", 11 | 1: "debris/bustcrate3.wav", 12 | 2: "debris/bustmetal2.wav", 13 | 3: "debris/bustflesh1.wav", 14 | 4: "debris/bustconcrete1.wav", 15 | 5: "debris/bustceiling.wav", 16 | 6: "debris/bustflesh1.wav", 17 | 7: "", 18 | 8: "debris/bustconcrete1.wav", 19 | } 20 | 21 | func _ready(): 22 | return 23 | targetNodes = get_meta("targetNodes") 24 | 25 | 26 | var nodePath = "Geometry/"+targetNodes 27 | var materialType = get_meta("materialType") 28 | if materialType == 7: 29 | unbreakable = true 30 | 31 | targetNodes = get_parent().get_parent().get_node(nodePath) 32 | targetNodes.set_meta("breakable",self) 33 | if has_meta("targetName"): 34 | targetName = get_meta("targetName") 35 | breakSound = get_parent().get_parent().createAudioPlayer3DfromName(matSound[materialType]) 36 | breakSound.translation = targetNodes.translation 37 | breakSound.unit_size = 10 38 | add_child(breakSound) 39 | 40 | func takeDamage(): 41 | toggle() 42 | 43 | func setStage(state): 44 | toggle() 45 | 46 | func toggle(): 47 | if unbreakable == true: 48 | return 49 | if targetNodes!= null: 50 | if breakSound!= null: 51 | breakSound.play() 52 | 53 | if targetNodes != null: 54 | if typeof(targetNodes) != TYPE_ARRAY: 55 | targetNodes.queue_free() 56 | 57 | if targetName != null: 58 | for i in get_tree().get_nodes_in_group(targetName): 59 | i.toggle() 60 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/func_button.gd: -------------------------------------------------------------------------------- 1 | extends Area 2 | 3 | 4 | var targetNodes 5 | var targetName = "" 6 | var sound 7 | var timer = null 8 | var cooldown = false 9 | func _ready(): 10 | 11 | targetName = get_meta("target") 12 | sound = get_node_or_null("sound") 13 | 14 | 15 | func _physics_process(delta): 16 | if cooldown == true: 17 | return 18 | 19 | for c in get_overlapping_bodies(): 20 | if c.is_in_group("hlTrigger"): 21 | cooldown = true 22 | if sound != null: 23 | sound.play() 24 | if targetName != null: 25 | toggle() 26 | 27 | if timer == null: 28 | timer = Timer.new() 29 | timer.wait_time = 1.5 30 | timer.connect("timeout", self, "coolDownOver") 31 | add_child(timer) 32 | timer.start() 33 | 34 | func setState(state): 35 | toggle() 36 | 37 | func toggle(): 38 | 39 | for i in get_tree().get_nodes_in_group(targetName): 40 | if "locked" in i: 41 | i.locked = false 42 | i.toggle() 43 | 44 | func coolDownOver(): 45 | cooldown = false 46 | timer.queue_free() 47 | timer = null 48 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/func_door.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Spatial 3 | 4 | 5 | var active = false 6 | var targetNodes = [] 7 | var scaleFactor 8 | var BBMax : Vector3 9 | var BBMin : Vector3 10 | var dimX 11 | var dimY 12 | var dimZ 13 | var dim 14 | var inc = Vector3.ZERO 15 | var lip = 0 16 | var rot = Vector3(0,0,0) 17 | var dir = Vector3(-1,0,0) 18 | var destScaler = Vector3(0,0,0) 19 | var destination = Vector3.ZERO 20 | var speed = 300 21 | var locked = false 22 | var angle 23 | var moveSound 24 | var lockedSound 25 | var target = null 26 | var open = false 27 | func _ready(): 28 | 29 | #if name == "G_DOOR": 30 | # breakpoint 31 | dim = get_meta("dim")#Vector3(dimX,dimY,dimZ) 32 | scaleFactor = get_meta("scaleFactor") 33 | if has_meta("lip"): lip = get_meta("lip") 34 | if has_meta("locked"): locked = true 35 | var targetNodesPath = get_meta("targetNodePaths") 36 | 37 | moveSound = get_node_or_null("moveSound") 38 | lockedSound = get_node_or_null("lockedSound") 39 | 40 | if has_meta("target"): 41 | target = get_meta("target") 42 | 43 | for i in targetNodesPath: 44 | var gp= get_parent().get_parent() 45 | targetNodes.append(gp.get_node("Geometry").get_node(i)) 46 | if has_meta("speed"): 47 | speed = get_meta("speed")*4 48 | #speed = get_meta("speed")*2 49 | 50 | if has_meta("angles"): 51 | rot = get_meta("angles") 52 | var yaw = deg2rad(rot.x) 53 | var pitch = deg2rad(rot.y) 54 | var roll = deg2rad(rot.z) 55 | 56 | dir.y = -(-cos(yaw)*sin(pitch)*sin(roll)-sin(yaw)*cos(roll)) 57 | dir.x = -(-sin(yaw)*sin(pitch)*sin(roll)+cos(yaw)*cos(roll)) 58 | dir.z = cos(pitch)*sin(roll) 59 | 60 | 61 | if abs(roll) >=0.01 and abs(yaw) >= 0.01: 62 | dir.y = -dir.z 63 | dir.z = 0 64 | 65 | #draw.drawLine(Vector3.ZERO,dir) 66 | 67 | if abs(dir.x) > 0.01: 68 | destScaler.x = 1 69 | if abs(dir.y) > 0.01: 70 | destScaler.y = 1 71 | if abs(dir.z) > 0.01: 72 | destScaler.z = 1 73 | 74 | 75 | destination = (dim*destScaler) - (destScaler*lip) 76 | 77 | 78 | elif has_meta("angle"): 79 | angle = get_meta("angle") 80 | 81 | dir = angle 82 | destination = angle*dim 83 | else: 84 | destination = dir*dim 85 | 86 | # draw.drawSphere(destination) 87 | #print(name,":",dir,":",destination) 88 | 89 | 90 | func _physics_process(delta): 91 | 92 | collisions() 93 | if !active: 94 | return 95 | 96 | 97 | #if abs(inc.y) >= abs(destination.y): 98 | # if abs(inc.x) >= abs(destination.x): 99 | # if abs(inc.z) >= abs(destination.z): 100 | # return 101 | 102 | for i in targetNodes: 103 | if abs(inc.x) < abs(destination.x): 104 | 105 | i.translation.x += dir.x * 0.0025 *speed*scaleFactor 106 | #inc.x += dir.x*0.00015*speed 107 | 108 | if abs(inc.y) < abs(destination.y): 109 | i.translation.y += dir.y *0.0025 *speed*scaleFactor 110 | #inc.y += dir.y*0.00015*speed 111 | 112 | if abs(inc.z) < abs(destination.z): 113 | i.translation.z += dir.z * 0.0025*speed*scaleFactor 114 | #inc.z += dir.z*0.00015*speed 115 | 116 | 117 | inc += dir*0.0025*speed*scaleFactor 118 | 119 | 120 | 121 | func collisions(): 122 | for c in get_node("interactionBox").get_overlapping_bodies(): 123 | if c.is_in_group("hlTrigger"): 124 | open() 125 | 126 | 127 | var flag = false 128 | 129 | func open(): 130 | #if open == true: 131 | # return 132 | 133 | # open = true 134 | 135 | 136 | if active == false and locked == false: 137 | active = true 138 | if target != null: 139 | for i in get_tree().get_nodes_in_group(target): 140 | i.toggle() 141 | if moveSound != null: 142 | moveSound.play() 143 | 144 | elif locked == true: 145 | if lockedSound != null: 146 | if !lockedSound.playing: 147 | lockedSound.play() 148 | 149 | func toggle(): 150 | locked = false 151 | 152 | 153 | if active == false: #and (locked == false and fromTrigger == false): 154 | active = true 155 | 156 | if target != null: 157 | for i in get_tree().get_nodes_in_group(target): 158 | i.toggle() 159 | 160 | if moveSound != null: 161 | moveSound.play() 162 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/func_door_rotating.gd: -------------------------------------------------------------------------------- 1 | extends Spatial 2 | 3 | 4 | var active = false 5 | var targetNodes = [] 6 | var scaleFactor 7 | var inc = Vector3.ZERO 8 | var lip = 0 9 | var rot = Vector3(0,0,0) 10 | var dir = Vector3.ZERO 11 | var rotAmount = deg2rad(90) 12 | var origin = Vector3.ZERO 13 | var rotDir = 1 14 | var rotInc = 0 15 | var locked = false 16 | var local = {} 17 | var axis = Vector3.ZERO 18 | var moveSound 19 | func _ready(): 20 | 21 | origin = get_meta("origin") 22 | scaleFactor = get_meta("scaleFactor") 23 | rotAmount = deg2rad(get_meta("rotAmount")) 24 | moveSound = get_node_or_null("moveSound") 25 | axis = get_meta("axis") 26 | 27 | if has_meta("rotDir"): 28 | rotDir = get_meta("rotDir") 29 | 30 | if has_meta("lip"): lip = get_meta("lip") 31 | var targetNodesPath = get_meta("targetNodePaths") 32 | for i in targetNodesPath: 33 | var gp= get_parent().get_parent() 34 | targetNodes.append(gp.get_node("Geometry").get_node(i)) 35 | 36 | if has_meta("angles"): 37 | rot = get_meta("angles") 38 | var yaw = deg2rad(rot.x) 39 | var pitch = deg2rad(rot.y) 40 | var roll = deg2rad(rot.z) 41 | 42 | dir.y = -cos(yaw)*sin(pitch)*sin(roll)-sin(yaw)*cos(roll) 43 | dir.x = -sin(yaw)*sin(pitch)*sin(roll)+cos(yaw)*cos(roll) 44 | dir.z = cos(pitch)*sin(roll) 45 | 46 | 47 | var initialRot = get_meta("initialRot") 48 | 49 | 50 | for i in targetNodes: 51 | local[i] = i.translation-origin 52 | if initialRot.x >0: 53 | i.rotation_degrees.x = -initialRot.x 54 | get_node("interactionBox").rotation_degrees.x = -initialRot.x 55 | if initialRot.y >0: 56 | i.rotation_degrees.y = initialRot.y 57 | get_node("interactionBox").rotation_degrees.y = initialRot.y 58 | if initialRot.z >0: 59 | i.rotation_degrees.z = initialRot.z 60 | get_node("interactionBox").rotation_degrees.z = initialRot.z 61 | 62 | func _physics_process(delta): 63 | 64 | collisions() 65 | if !active: 66 | return 67 | #thetha = 0 68 | if rotInc < rotAmount: 69 | for i in targetNodes: 70 | 71 | if axis.x != 0: 72 | i.rotation_degrees.x += axis.x* rotDir 73 | 74 | if axis.y != 0: 75 | i.rotation_degrees.y += axis.y* rotDir 76 | 77 | if axis.z != 0: 78 | i.rotation_degrees.z += axis.z* rotDir 79 | 80 | 81 | pass 82 | rotInc += deg2rad(1) 83 | get_node("interactionBox").translation = Vector3.ZERO 84 | 85 | if axis.x == 1: 86 | get_node("interactionBox").rotation_degrees.x += 0.001* rotDir 87 | 88 | if axis.y == 1: 89 | get_node("interactionBox").rotation_degrees.y += 0.001* rotDir 90 | 91 | if axis.z == 1: 92 | get_node("interactionBox").rotation_degrees.z += 0.001 * rotDir 93 | 94 | get_node("interactionBox").translation = origin 95 | 96 | 97 | 98 | 99 | 100 | func collisions(): 101 | for c in get_node("interactionBox").get_overlapping_bodies(): 102 | if c.get_class() == "StaticBody": 103 | if !targetNodes.find(c.get_parent()): 104 | pass 105 | 106 | 107 | if c.is_in_group("hlTrigger"): 108 | active = true 109 | if moveSound: 110 | moveSound.play() 111 | 112 | 113 | func setState(state): 114 | toggle() 115 | 116 | func toggle(): 117 | if active == false:#and locked == false: 118 | if moveSound: 119 | moveSound.play() 120 | active = true 121 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/func_ladder.gd: -------------------------------------------------------------------------------- 1 | extends Area 2 | 3 | func _ready(): 4 | self.connect("body_entered",self,"_on_ladder_body_entered") 5 | self.connect("body_exited",self,"_on_ladder_body_exited") 6 | 7 | 8 | 9 | func _on_ladder_body_entered(body): 10 | if body.is_in_group("hlTrigger"): 11 | if body.has_method("enterLadder"): 12 | body.enterLadder() 13 | 14 | 15 | 16 | func _on_ladder_body_exited(body): 17 | if body.is_in_group("hlTrigger"): 18 | if body.has_method("exitLadder"): 19 | body.exitLadder() 20 | 21 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/func_pendulum.gd: -------------------------------------------------------------------------------- 1 | extends Spatial 2 | 3 | 4 | var active = true 5 | var targetNodes = [] 6 | var scaleFactor 7 | var BBMax : Vector3 8 | var BBMin : Vector3 9 | var dimX 10 | var dimY 11 | var dimZ 12 | var dim 13 | var inc = Vector3.ZERO 14 | var lip = 0 15 | var rot = Vector3(0,0,0) 16 | var dir = Vector3.ZERO 17 | var rotAmount = 90 18 | var origin = Vector3.ZERO 19 | var rotInc = 0 20 | var axis = Vector3(0,1,0) 21 | func _ready(): 22 | 23 | dim = get_meta("dim")#Vector3(dimX,dimY,dimZ) 24 | origin = get_meta("origin") 25 | scaleFactor = get_meta("scaleFactor") 26 | axis = get_meta("axis") 27 | var targetNodesPath = get_meta("targetNodePaths") 28 | 29 | 30 | for i in targetNodesPath: 31 | var gp= get_parent().get_parent() 32 | targetNodes.append(gp.get_node("Geometry").get_node(i)) 33 | 34 | 35 | func _physics_process(delta): 36 | 37 | if !active: 38 | return 39 | 40 | for i in targetNodes: 41 | if axis.x == 1: 42 | i.rotation_degrees.x += 2 43 | if axis.y == 1: 44 | i.rotation_degrees.y += 2 45 | 46 | if axis.z == 1: 47 | i.rotation_degrees.z += 2 48 | 49 | 50 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/func_rot_button.gd: -------------------------------------------------------------------------------- 1 | extends Area 2 | 3 | 4 | var targetNodes = [] 5 | var targetName = "" 6 | var sound 7 | var timer = null 8 | var cooldown = false 9 | 10 | 11 | var active = false 12 | var scaleFactor 13 | var BBMax : Vector3 14 | var BBMin : Vector3 15 | var dimX 16 | var dimY 17 | var dimZ 18 | var dim 19 | var inc = Vector3.ZERO 20 | var lip = 0 21 | var rot = Vector3(0,0,0) 22 | var dir = Vector3.ZERO 23 | var rotAmount = 90 24 | var origin = Vector3.ZERO 25 | var rotInc = 0 26 | var axis = Vector3(0,1,0) 27 | 28 | func _ready(): 29 | targetName = get_meta("target") 30 | sound = get_node_or_null("sound") 31 | dim = get_meta("dim")#Vector3(dimX,dimY,dimZ) 32 | origin = get_meta("origin") 33 | scaleFactor = get_meta("scaleFactor") 34 | axis = get_meta("axis") 35 | var targetNodesPath = get_meta("targetNodePaths") 36 | 37 | 38 | for i in targetNodesPath: 39 | var gp= get_parent().get_parent() 40 | targetNodes.append(gp.get_node("Geometry").get_node(i)) 41 | 42 | 43 | func _physics_process(delta): 44 | 45 | for c in get_overlapping_bodies(): 46 | if c.is_in_group("hlTrigger"): 47 | active = true 48 | activate() 49 | if !active: 50 | return 51 | 52 | for i in targetNodes: 53 | if abs(axis.x) == 1: 54 | i.rotation_degrees.x += axis.x*2 55 | if abs(axis.y) == 1: 56 | i.rotation_degrees.y += axis.y*2 57 | 58 | if abs(axis.z) == 1: 59 | i.rotation_degrees.z += axis.z*2 60 | 61 | 62 | func toggle(state): 63 | activate() 64 | 65 | func activate(): 66 | 67 | for i in get_tree().get_nodes_in_group(targetName): 68 | if "locked" in i: 69 | i.locked = false 70 | i.activate() 71 | 72 | func coolDownOver(): 73 | cooldown = false 74 | timer.queue_free() 75 | timer = null 76 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/func_rotating.gd: -------------------------------------------------------------------------------- 1 | extends Spatial 2 | 3 | 4 | var active = true 5 | var targetNodes = [] 6 | var scaleFactor 7 | var BBMax : Vector3 8 | var BBMin : Vector3 9 | var dimX 10 | var dimY 11 | var dimZ 12 | var dim 13 | var inc = Vector3.ZERO 14 | var lip = 0 15 | var rot = Vector3(0,0,0) 16 | var dir = Vector3.ZERO 17 | var rotAmount = 90 18 | var origin = Vector3.ZERO 19 | var rotInc = 0 20 | var axis = Vector3(0,1,0) 21 | func _ready(): 22 | 23 | dim = get_meta("dim")#Vector3(dimX,dimY,dimZ) 24 | origin = get_meta("origin") 25 | scaleFactor = get_meta("scaleFactor") 26 | axis = get_meta("axis") 27 | var targetNodesPath = get_meta("targetNodePaths") 28 | 29 | 30 | for i in targetNodesPath: 31 | 32 | var gp= get_parent().get_parent() 33 | var node = gp.get_node("Geometry").get_node(i) 34 | node.collision_layer = 0 35 | node.collision_mask = 0 36 | targetNodes.append(node) 37 | 38 | 39 | 40 | func _physics_process(delta): 41 | 42 | if !active: 43 | return 44 | 45 | for i in targetNodes: 46 | if i == null: 47 | continue 48 | 49 | if axis.x == 1: 50 | i.rotation_degrees.x += 2 51 | if axis.y == 1: 52 | i.rotation_degrees.y += 2 53 | 54 | if axis.z == 1: 55 | i.rotation_degrees.z += 2 56 | 57 | 58 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/func_track_train.gd: -------------------------------------------------------------------------------- 1 | extends Spatial 2 | 3 | var targetNodes = [] 4 | var pathName = [] 5 | var pathPosArr = [] 6 | var refArr = {} 7 | var triggers = [] 8 | var scaleFactor 9 | var initialRot = 0 10 | var moveSound : AudioStreamPlayer3D = null 11 | 12 | onready var path = null#get_parent().find_node("testo",true,false) 13 | onready var pathFollow : PathFollow =null# path.get_child(0) 14 | func _ready(): 15 | var targetNodesPath = get_meta("targetNodePaths") 16 | var pathName = get_meta("path") 17 | 18 | for i in targetNodesPath: 19 | var gp= get_parent() 20 | targetNodes.append(gp.get_node("Geometry").get_node(i)) 21 | 22 | scaleFactor = get_meta("scaleFactor") 23 | 24 | if has_meta("pathName"): 25 | var nameStr= get_meta("pathName") 26 | path = get_parent().find_node(nameStr,true,false) 27 | pathFollow = path.get_child(0) 28 | 29 | var ref = targetNodes[0].translation 30 | 31 | var triggerTargets = path.get_meta_list() 32 | for t in triggerTargets: 33 | var pos = path.get_meta(t) 34 | if typeof(pos) == TYPE_VECTOR3: 35 | triggers.append({"name":t,"position":pos}) 36 | 37 | for i in pathName:#name of each path node 38 | var destination = get_parent().find_node(i,true,false) 39 | if destination != null: 40 | pathPosArr.append(destination.translation) 41 | 42 | moveSound = get_node("moveSound") 43 | 44 | 45 | 46 | for i in targetNodes:#for all target faces set origin to ref and add path translation 47 | var firstPosNode = get_parent().find_node(pathName[0],true,false) 48 | i.translation -= ref 49 | refArr[i] = i.translation 50 | i.translation += pathPosArr[0] 51 | 52 | 53 | translation = pathPosArr[0] 54 | 55 | if pathPosArr.size() > 2: 56 | var a : Vector2 = Vector2(pathPosArr[0].x,pathPosArr[0].z) 57 | var b : Vector2 = Vector2(pathPosArr[1].x,pathPosArr[1].z) 58 | var diff = (b-a).normalized() 59 | initialRot = atan2(diff.y,diff.x) 60 | 61 | 62 | 63 | pathPosArr.pop_front() 64 | 65 | 66 | func setOrigin(node,origin): 67 | for c in node.get_children(): 68 | if "translation" in c: 69 | c.translation = node.translation 70 | 71 | node.translation = origin 72 | 73 | func _physics_process(delta): 74 | 75 | 76 | pathFollow.offset += delta*100*scaleFactor 77 | 78 | translation = pathFollow.translation 79 | 80 | for i in triggers: 81 | if pathFollow.translation.distance_to(i["position"]) < 10: 82 | get_tree().call_group(i["name"],"activate") 83 | triggers.erase(i) 84 | 85 | 86 | for n in targetNodes: 87 | n.translation = pathFollow.translation 88 | n.rotation = pathFollow.rotation - Vector3(0,initialRot,0) 89 | 90 | 91 | 92 | if moveSound != null: 93 | if !moveSound.playing: 94 | if moveSound.stream != null: 95 | moveSound.stream.loop_mode = AudioStreamSample.LOOP_FORWARD 96 | 97 | moveSound.unit_db = 10 98 | moveSound.play() 99 | 100 | 101 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/func_train.gd: -------------------------------------------------------------------------------- 1 | extends Spatial 2 | 3 | var targetNodes = [] 4 | var pathName = [] 5 | var pathPosArr = [] 6 | var refArr = {} 7 | var scaleFactor 8 | func _ready(): 9 | var targetNodesPath = get_meta("targetNodePaths") 10 | var pathName = get_meta("path") 11 | var scaleFactor = get_meta("scaleFactor") 12 | for i in targetNodesPath: 13 | var gp= get_parent() 14 | targetNodes.append(gp.get_node("Geometry").get_node(i)) 15 | 16 | 17 | var ref = targetNodes[0].translation 18 | 19 | for i in targetNodes: 20 | 21 | var firstPosNode = get_parent().find_node(pathName[0],true,false) 22 | i.translation -= ref 23 | refArr[i] = i.translation 24 | i.translation += firstPosNode.translation 25 | 26 | 27 | pathName.pop_front() 28 | 29 | for i in pathName: 30 | var destination = get_parent().find_node(i,true,false) 31 | if destination != null: 32 | pathPosArr.append(destination.translation) 33 | 34 | 35 | 36 | 37 | func setOrigin(node,origin): 38 | for c in node.get_children(): 39 | if "translation" in c: 40 | c.translation = node.translation 41 | 42 | node.translation = origin 43 | 44 | func _physics_process(delta): 45 | 46 | for n in targetNodes: 47 | if n!= null: 48 | n.translation = n.translation.linear_interpolate(pathPosArr[0]+refArr[n],0.0001) 49 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/light.gd: -------------------------------------------------------------------------------- 1 | extends Light 2 | 3 | func setState(state): 4 | visible = state 5 | 6 | 7 | func toggle(): 8 | visible = !visible 9 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/multi_manager.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | 4 | var targetGroups 5 | 6 | func _ready(): 7 | targetGroups = get_meta("targetGroups") 8 | 9 | func setState(state): 10 | toggle() 11 | 12 | func toggle(): 13 | for group in targetGroups: 14 | for i in get_tree().get_nodes_in_group(group["name"]): 15 | if i!=self and i.get_class() != "Node": 16 | var script = load("res://addons/gldsrcBSP/funcScripts/trigger_auto.gd") 17 | var timer = Node.new() 18 | 19 | timer.set_meta("delay",group["delay"]) 20 | timer.set_meta("target",group["name"]) 21 | timer.set_script(script) 22 | add_child(timer) 23 | #i.activate() 24 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/trigger.gd: -------------------------------------------------------------------------------- 1 | extends Area 2 | 3 | 4 | var targetName 5 | var oneshot = false 6 | func _ready(): 7 | targetName = get_meta("target") 8 | if has_meta("trigger_once"): 9 | oneshot = true 10 | 11 | 12 | 13 | func _physics_process(delta): 14 | for i in get_overlapping_bodies(): 15 | if i.is_in_group("hlTrigger"): 16 | get_tree().call_group(targetName,"toggle") 17 | queue_free() 18 | 19 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/trigger_auto.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | 4 | var targetName 5 | var oneshot = false 6 | 7 | 8 | 9 | func _ready(): 10 | var delay = int(get_meta("delay")) 11 | targetName = get_meta("target") 12 | 13 | var timer = Timer.new() 14 | timer.wait_time = max(delay,0.0001) 15 | timer.one_shot = true 16 | timer.autostart = true 17 | timer.connect("timeout",self,"activate") 18 | add_child(timer) 19 | 20 | 21 | 22 | func activate(): 23 | get_tree().call_group(targetName,"toggle") 24 | queue_free() 25 | 26 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/trigger_changelevel.gd: -------------------------------------------------------------------------------- 1 | extends Area 2 | 3 | 4 | var mapName 5 | 6 | func _ready(): 7 | mapName = get_meta("mapName").to_lower() 8 | 9 | 10 | func _process(delta): 11 | for i in get_overlapping_bodies(): 12 | if i.is_in_group("hlTrigger"): 13 | get_tree().call_group("worldManager","changeMap",mapName) 14 | 15 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/trigger_push.gd: -------------------------------------------------------------------------------- 1 | extends Area 2 | 3 | func _ready(): 4 | self.connect("body_entered",self,"_on_ladder_body_entered") 5 | self.connect("body_exited",self,"_on_ladder_body_exited") 6 | 7 | 8 | 9 | func _on_ladder_body_entered(body): 10 | if body.is_in_group("hlTrigger"): 11 | print("enter push") 12 | #body.enterLadder() 13 | 14 | 15 | 16 | func _on_ladder_body_exited(body): 17 | if body.is_in_group("hlTrigger"): 18 | print("exit push") 19 | #body.exitLadder() 20 | 21 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/trigger_relay.gd: -------------------------------------------------------------------------------- 1 | extends Spatial 2 | 3 | 4 | var targetName 5 | var target 6 | var delay 7 | var state 8 | func _ready(): 9 | targetName = get_meta("target") 10 | target = get_meta("targetName") 11 | delay = get_meta("delay") 12 | state = bool(get_meta("state")) 13 | 14 | 15 | func toggle(): 16 | get_tree().call_group(targetName,"setState",state) 17 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/trigger_teleport.gd: -------------------------------------------------------------------------------- 1 | extends Area 2 | 3 | 4 | var targetName 5 | var oneshot = false 6 | func _ready(): 7 | targetName = get_meta("target") 8 | if has_meta("trigger_once"): 9 | oneshot = true 10 | 11 | 12 | 13 | 14 | 15 | func _physics_process(delta): 16 | for i in get_overlapping_bodies(): 17 | if i.is_in_group("hlTrigger"): 18 | get_tree().call_group(targetName,"toggle") 19 | queue_free() 20 | 21 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/funcScripts/water.gd: -------------------------------------------------------------------------------- 1 | extends Area 2 | 3 | func _ready(): 4 | self.connect("body_entered",self,"_on_ladder_body_entered") 5 | self.connect("body_exited",self,"_on_ladder_body_exited") 6 | 7 | 8 | 9 | func _on_ladder_body_entered(body): 10 | 11 | if body.is_in_group("hlTrigger"): 12 | if body.has_method("enterWater"): 13 | body.enterLadder() 14 | 15 | 16 | 17 | func _on_ladder_body_exited(body): 18 | 19 | if body.is_in_group("hlTrigger"): 20 | if body.has_method("exitWater"): 21 | body.exitLadder() 22 | 23 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/lightmapAtlas.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Node 3 | 4 | var curLineY = 0 5 | var curLineMaxH = 0 6 | var allLineMaxH = 0 7 | var image : Image 8 | var maxW = 800 9 | var curPos = Vector2(0,0) 10 | var texture : ImageTexture 11 | var faceToOrigLM = {} 12 | var atlasImgDimArr = [] 13 | var atlasImgDimArrImg = [] 14 | var atlasPos = [] 15 | var atlasDim = [] 16 | 17 | # Called when the node enters the scene tree for the first time. 18 | func _ready(): 19 | image = Image.new() 20 | image.create(maxW,10,true,Image.FORMAT_RGB8) 21 | texture = ImageTexture.new() 22 | set_meta("hidden",true) 23 | #texture.flags = 0 24 | 25 | 26 | func addToAtlas(fmap,index = 1): 27 | #fmap.save_png("lightMaps/"+String(index)+".png") 28 | var dim = fmap.get_size() 29 | var mapSize = image.get_size() 30 | 31 | 32 | if (curPos.x + dim.x) > maxW: 33 | curPos.y+=curLineMaxH 34 | curLineMaxH = 0 35 | curPos.x=0 36 | 37 | if dim.y > curLineMaxH: curLineMaxH = dim.y 38 | 39 | var localRect = Rect2(Vector2.ZERO,dim) 40 | 41 | if curPos.y + dim.y > image.get_size().y: 42 | image.crop(maxW,curPos.y + dim.y) 43 | 44 | image.blit_rect(fmap,localRect,Vector2(curPos.x,curPos.y)) 45 | curPos.x += dim.x 46 | return Vector2(curPos-Vector2(dim.x,0)) 47 | 48 | 49 | func addToAtlas2(fmap,index = 1): 50 | var dim = fmap.get_size() 51 | atlasImgDimArr.append(dim) 52 | atlasImgDimArrImg.append(fmap) 53 | 54 | func getSize(): 55 | return image.get_size() 56 | 57 | func getTexture(): 58 | texture.create_from_image(image) 59 | #texture.flags = 0 60 | return texture 61 | 62 | func initAtlas(): 63 | var atlasArr =Geometry.make_atlas(atlasImgDimArr) 64 | atlasPos = atlasArr["points"] 65 | atlasDim = atlasArr["size"] 66 | 67 | image = Image.new() 68 | image.create(atlasDim.x,atlasDim.y,true,Image.FORMAT_RGB8) 69 | texture = ImageTexture.new() 70 | #texture.flags = 0 71 | 72 | 73 | for i in atlasImgDimArr.size(): 74 | var source = Rect2(Vector2.ZERO,atlasImgDimArrImg[i].get_size()) 75 | image.blit_rect(atlasImgDimArrImg[i],source,atlasPos[i]) 76 | 77 | 78 | #return {"rectArr":atlasArr} 79 | #for f in atlasImgDimArrImg: 80 | 81 | #image.crop(maxW,curPos.y + dim.y) 82 | #for i in atla 83 | #image.resize(image.get_size().x,image.get_size().y,Image.INTERPOLATE_TRILINEAR) 84 | texture.create_from_image(image) 85 | #texture.flags = 0 86 | 87 | #image.save_png("atlas.png") 88 | 89 | 90 | 91 | 92 | return {"texture":texture,"rects":atlasArr} 93 | 94 | 95 | func saveToFile(): 96 | texture.set_data(image) 97 | #texture.flags = 0 98 | image.save_png("atlas.png") 99 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/player/Crosshair.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Node2D 3 | 4 | 5 | export var gap = 5 6 | export var length = 5 7 | export var thickness = 1 8 | export(Color, RGBA) var color = Color(1,1,0,1) 9 | 10 | onready var right = $"right" 11 | onready var left = $"left" 12 | onready var up = $"up" 13 | onready var down = $"down" 14 | # Called when the node enters the scene tree for the first time. 15 | 16 | 17 | func _ready(): 18 | gap() 19 | position = get_viewport_rect().size / 2 20 | 21 | 22 | func _physics_process(delta): 23 | #gap() 24 | color() 25 | thickness() 26 | 27 | func gap(): 28 | 29 | right.points[0].x = gap 30 | right.points[1].x = gap+length 31 | 32 | left.points[0].x = -gap 33 | left.points[1].x = -(gap+length) 34 | 35 | up.points[1].y = -gap 36 | up.points[0].y = -(gap+length) 37 | 38 | down.points[1].y = gap 39 | down.points[0].y = gap+length 40 | 41 | func color(): 42 | right.default_color = color 43 | left.default_color = color 44 | down.default_color = color 45 | up.default_color = color 46 | 47 | func thickness(): 48 | right.width = thickness 49 | left.width = thickness 50 | down.width = thickness 51 | up.width = thickness 52 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/player/UI.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://icon.png" type="Texture" id=1] 4 | [ext_resource path="res://scripts/player/Crosshair.gd" type="Script" id=2] 5 | 6 | [node name="UI" type="Control"] 7 | anchor_right = 1.0 8 | anchor_bottom = 1.0 9 | __meta__ = { 10 | "_edit_use_anchors_": false 11 | } 12 | 13 | [node name="TextureRect" type="TextureRect" parent="."] 14 | anchor_left = 0.5 15 | anchor_top = 0.5 16 | anchor_right = 0.5 17 | anchor_bottom = 0.5 18 | margin_left = 487.5 19 | margin_top = 276.0 20 | margin_right = 496.5 21 | margin_bottom = 284.0 22 | texture = ExtResource( 1 ) 23 | expand = true 24 | stretch_mode = 1 25 | __meta__ = { 26 | "_edit_use_anchors_": false 27 | } 28 | 29 | [node name="Crosshair" type="Node2D" parent="."] 30 | position = Vector2( 512, 300 ) 31 | script = ExtResource( 2 ) 32 | gap = 8 33 | length = 10 34 | thickness = 5 35 | color = Color( 0.858824, 0, 0, 0.552941 ) 36 | 37 | [node name="right" type="Line2D" parent="Crosshair"] 38 | points = PoolVector2Array( 8, 0, 18, 0 ) 39 | width = 5.0 40 | default_color = Color( 0.858824, 0, 0, 0.552941 ) 41 | 42 | [node name="left" type="Line2D" parent="Crosshair"] 43 | points = PoolVector2Array( -8, 0, -18, 0 ) 44 | width = 5.0 45 | default_color = Color( 0.858824, 0, 0, 0.552941 ) 46 | 47 | [node name="up" type="Line2D" parent="Crosshair"] 48 | points = PoolVector2Array( 0, -18, 0, -8 ) 49 | width = 5.0 50 | default_color = Color( 0.858824, 0, 0, 0.552941 ) 51 | 52 | [node name="down" type="Line2D" parent="Crosshair"] 53 | position = Vector2( 0.105103, 0 ) 54 | points = PoolVector2Array( 0, 18, 0, 8 ) 55 | width = 5.0 56 | default_color = Color( 0.858824, 0, 0, 0.552941 ) 57 | round_precision = 14 58 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/player/debug/CanvasLayer.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/gldsrcBSP/player/debug/debug.gd" type="Script" id=1] 4 | 5 | [node name="CanvasLayer" type="CanvasLayer"] 6 | 7 | [node name="VBoxContainer" type="VBoxContainer" parent="."] 8 | margin_right = 40.0 9 | margin_bottom = 40.0 10 | script = ExtResource( 1 ) 11 | __meta__ = { 12 | "_edit_use_anchors_": false 13 | } 14 | 15 | [node name="fps" type="Label" parent="VBoxContainer"] 16 | margin_right = 63.0 17 | margin_bottom = 14.0 18 | text = "fps" 19 | __meta__ = { 20 | "_edit_use_anchors_": false 21 | } 22 | 23 | [node name="drawCalls" type="Label" parent="VBoxContainer"] 24 | margin_top = 18.0 25 | margin_right = 63.0 26 | margin_bottom = 32.0 27 | text = "draw calls" 28 | __meta__ = { 29 | "_edit_use_anchors_": false 30 | } 31 | 32 | [node name="vertices" type="Label" parent="VBoxContainer"] 33 | margin_top = 36.0 34 | margin_right = 63.0 35 | margin_bottom = 50.0 36 | text = "vertices" 37 | __meta__ = { 38 | "_edit_use_anchors_": false 39 | } 40 | 41 | [node name="material" type="Label" parent="VBoxContainer"] 42 | margin_top = 54.0 43 | margin_right = 63.0 44 | margin_bottom = 68.0 45 | text = "material" 46 | __meta__ = { 47 | "_edit_use_anchors_": false 48 | } 49 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/player/debug/debug.gd: -------------------------------------------------------------------------------- 1 | extends VBoxContainer 2 | 3 | 4 | # Called when the node enters the scene tree for the first time. 5 | func _ready(): 6 | pass # Replace with function body. 7 | 8 | # Called every frame. 'delta' is the elapsed time since the previous frame. 9 | func _process(_delta): 10 | $"fps".text = "fps:" + str(Engine.get_frames_per_second()) 11 | $"drawCalls".text = "draw calls:" + str(Performance.get_monitor(Performance.RENDER_DRAW_CALLS_IN_FRAME)) 12 | $"vertices".text = "vertices:" + str(Performance.get_monitor(Performance.RENDER_VERTICES_IN_FRAME)) 13 | $"material".text = "materials:" + str(Performance.get_monitor(Performance.RENDER_MATERIAL_CHANGES_IN_FRAME)) 14 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/player/player.gd: -------------------------------------------------------------------------------- 1 | extends KinematicBody 2 | 3 | export var speed = 15 4 | var mouseSensitivity = 0.05 5 | var direction = Vector3() 6 | var accHor = Vector3() 7 | var hp = 100 8 | var dead = false 9 | export var gravity = 1 10 | export(NodePath) var bspNodePath = null 11 | var jumpSpeed = 0.5 12 | 13 | var initalGravity = gravity 14 | var gravityVelo = Vector3() 15 | var onGround = false 16 | var jumpSound = false 17 | onready var colShape = $"CollisionShape" 18 | onready var camera = $"Camera" 19 | onready var footCast = $"footCast" 20 | onready var initialShapeDim = Vector2(colShape.shape.radius,colShape.shape.height) 21 | onready var lastStep = translation 22 | onready var lastMat = "-" 23 | onready var footstepSound = $"footstepSound" 24 | onready var bspNode = get_node(bspNodePath) 25 | onready var shootCast = $"Camera/shootCast" 26 | 27 | var footStepDict = { 28 | "C":["player/pl_step1.wav","player/pl_step2.wav"], 29 | "M":["player/pl_metal1.wav","player/pl_metal2.wav"], 30 | "D":["player/pl_dirt1.wav","player/pl_dirt2.wav","player/pl_dirt3.wav"], 31 | "V":["player/pl_duct1.wav"], 32 | "G":["player/pl_grate1.wav","player/pl_grate4.wav"], 33 | "T":["player/pl_tile1.wav","player/pl_tile2.wav","player/pl_tile3.wav","player/pl_tile4.wav"], 34 | "S":["player/pl_slosh1.wav","player/pl_slosh2.wav","player/pl_slosh3.wav","player/pl_slosh4.wav"], 35 | "W":["debris/wood1.wav","debris/wood2.wav","debris/wood3.wav"], 36 | "P":["debris/glass1.wav","debris/glass2.wav","debris/glass3.wav"], 37 | "Y":["debris/glass1.wav","debris/glass2.wav","debris/glass3.wav"], 38 | "F":["weapons/bullet_hit1.wav","weapons/bullet_hit1.wav","weapons/bullet_hit1.wav"] 39 | 40 | 41 | } 42 | 43 | var cachedSounds = {} 44 | 45 | func _ready(): 46 | var err = bspNode.connect("playerSpawnSignal",self,"setSpawn") 47 | Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) 48 | 49 | 50 | func _input(event): 51 | if dead: 52 | return 53 | if event is InputEventMouseMotion: 54 | rotate_y(deg2rad(-event.relative.x * mouseSensitivity)) 55 | camera.rotate_x(deg2rad(-event.relative.y * mouseSensitivity)) 56 | camera.rotation.x = clamp(camera.rotation.x, deg2rad(-89),deg2rad(89)) 57 | 58 | func _physics_process(delta): 59 | #cameraStuff() 60 | onGround = is_on_floor() 61 | if hp == 0: 62 | die() 63 | 64 | 65 | var collider = footCast.get_collider() 66 | if collider != null: 67 | onGround = true 68 | #print(onGround) 69 | shoot() 70 | footsteps() 71 | direction = Vector3.ZERO 72 | 73 | if !onGround: 74 | gravityVelo += Vector3.DOWN * gravity * delta 75 | else: 76 | gravityVelo = -get_floor_normal() * 0.01 77 | 78 | 79 | 80 | if Input.is_action_just_pressed("ui_accept") and onGround: 81 | gravityVelo = Vector3.UP * jumpSpeed 82 | var mat = getFootMaterial() 83 | if mat!=null: 84 | playMatStepSound(mat) 85 | 86 | 87 | 88 | if Input.is_action_pressed("ui_up"): 89 | direction -= transform.basis.z 90 | elif Input.is_action_pressed("ui_down"): 91 | direction += transform.basis.z 92 | 93 | if Input.is_action_pressed("ui_left"): 94 | direction -= transform.basis.x 95 | elif Input.is_action_pressed("ui_right"): 96 | direction += transform.basis.x 97 | 98 | if Input.is_action_just_pressed("crouch"): 99 | colShape.shape.radius = initialShapeDim.x * 0.25 100 | colShape.shape.height = initialShapeDim.y * 0.25 101 | 102 | if Input.is_action_just_released("crouch"): 103 | colShape.shape.radius = initialShapeDim.x 104 | colShape.shape.height = initialShapeDim.y 105 | 106 | direction = direction.normalized() 107 | if dead: 108 | direction = Vector3.ZERO 109 | 110 | 111 | direction += gravityVelo 112 | move_and_slide(direction*speed,Vector3.UP,false,4,0.758,false) 113 | 114 | for index in get_slide_count(): 115 | var collision = get_slide_collision(index) 116 | 117 | if collision.collider.get_class() == "RigidBody": 118 | collision.collider.apply_central_impulse(-collision.normal * 1) 119 | 120 | 121 | func setSpawn(dict): 122 | #print(dict) 123 | translation = dict["pos"] 124 | rotation_degrees.y = dict["rot"]+90 125 | 126 | 127 | 128 | func enterLadder(): 129 | print("player enter ladder") 130 | gravity = -initalGravity 131 | 132 | func exitLadder(): 133 | print("player exit ladder") 134 | gravity = initalGravity 135 | 136 | func die(): 137 | if dead: 138 | return 139 | camera.rotate_z(deg2rad(90)) 140 | dead = true 141 | colShape.shape.radius = initialShapeDim.x * 0.01 142 | colShape.shape.height = initialShapeDim.y * 0.01 143 | return 144 | 145 | func footsteps(): 146 | 147 | if direction.length() < 0.1 and jumpSound == false: 148 | return 149 | 150 | var collider = footCast.get_collider() 151 | if collider == null: 152 | return 153 | 154 | var matType = getFootMaterial() 155 | 156 | if matType == null: 157 | return 158 | 159 | 160 | 161 | if footStepDict.has(matType): 162 | if translation.distance_to(lastStep) < 2 and lastMat == matType: 163 | lastMat = matType 164 | return 165 | 166 | lastMat = matType 167 | lastStep = translation 168 | 169 | playMatStepSound(matType) 170 | 171 | 172 | func getFootMaterial(): 173 | var collider = footCast.get_collider() 174 | if collider == null: 175 | return null 176 | 177 | if collider.has_meta("materialType"): 178 | var matType = collider.get_meta("materialType") 179 | return matType 180 | else: 181 | return null 182 | 183 | func playMatStepSound(mat): 184 | if footStepDict.has(mat): 185 | var randomIndex = randi()%footStepDict[mat].size() 186 | 187 | var soundFilePath = footStepDict[mat][randomIndex] 188 | var stream = null 189 | if !cachedSounds.has(soundFilePath): 190 | cachedSounds[soundFilePath] = bspNode.loadSound(soundFilePath) 191 | 192 | stream = cachedSounds[soundFilePath] 193 | 194 | if footstepSound.playing == false: 195 | footstepSound.stream = stream 196 | 197 | footstepSound.play() 198 | 199 | 200 | func shoot(): 201 | return 202 | var collider = shootCast.get_collider() 203 | if collider == null: 204 | return 205 | 206 | 207 | 208 | if Input.is_action_just_pressed("shoot"): 209 | direction -= transform.basis.z 210 | var ap = AudioStreamPlayer.new() 211 | ap.stream = bspNode.loadSound("weapons/pl_gun3.wav") 212 | ap.volume_db*= 0.005 213 | add_child(ap) 214 | ap.play() 215 | 216 | if collider.has_meta("breakable"): 217 | var breakNode = collider.get_meta("breakable") 218 | breakNode.takeDamage() 219 | if collider.has_method("takeDamage"): 220 | collider.takeDamage 221 | 222 | func cameraStuff(): 223 | var ninety = deg2rad(90) 224 | var rotY = rotation.y + ninety 225 | #LineDraw.drawLine(translation,translation+Vector3(cos(rotY),0,-sin(rotY))*10)# 226 | 227 | 228 | var x = cos(rotY)*cos(camera.rotation.x) 229 | var y = sin(camera.rotation.x) 230 | var z = -sin(rotY)*cos(camera.rotation.x) 231 | 232 | var origin = translation 233 | #LineDraw.drawLine(origin,origin+Vector3(x,y,z)*100)# 234 | 235 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/player/player.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://addons/gldsrcBSP/player/player.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/gldsrcBSP/player/Crosshair.gd" type="Script" id=3] 5 | [ext_resource path="res://addons/gldsrcBSP/player/debug/CanvasLayer.tscn" type="PackedScene" id=4] 6 | 7 | [sub_resource type="CylinderShape" id=1] 8 | height = 2.65987 9 | 10 | [node name="KinematicBody" type="KinematicBody" groups=[ 11 | "hlTrigger", 12 | "player", 13 | ]] 14 | script = ExtResource( 1 ) 15 | 16 | [node name="Camera" type="Camera" parent="."] 17 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.87452, 0 ) 18 | far = 8192.0 19 | 20 | [node name="CanvasLayer" parent="Camera" instance=ExtResource( 4 )] 21 | 22 | [node name="UI" type="Control" parent="Camera"] 23 | anchor_right = 1.0 24 | anchor_bottom = 1.0 25 | __meta__ = { 26 | "_edit_use_anchors_": false 27 | } 28 | 29 | [node name="Crosshair" type="Node2D" parent="Camera/UI"] 30 | position = Vector2( 512, 300 ) 31 | script = ExtResource( 3 ) 32 | color = Color( 0.92549, 0.203922, 0.0352941, 1 ) 33 | 34 | [node name="right" type="Line2D" parent="Camera/UI/Crosshair"] 35 | points = PoolVector2Array( 5, 0, 10, 0 ) 36 | width = 1.0 37 | default_color = Color( 0.92549, 0.203922, 0.0352941, 1 ) 38 | 39 | [node name="left" type="Line2D" parent="Camera/UI/Crosshair"] 40 | points = PoolVector2Array( -5, 0, -10, 0 ) 41 | width = 1.0 42 | default_color = Color( 0.92549, 0.203922, 0.0352941, 1 ) 43 | 44 | [node name="up" type="Line2D" parent="Camera/UI/Crosshair"] 45 | points = PoolVector2Array( 0, -10, 0, -5 ) 46 | width = 1.0 47 | default_color = Color( 0.92549, 0.203922, 0.0352941, 1 ) 48 | 49 | [node name="down" type="Line2D" parent="Camera/UI/Crosshair"] 50 | position = Vector2( 0.105103, 0 ) 51 | points = PoolVector2Array( 0, 10, 0, 5 ) 52 | width = 1.0 53 | default_color = Color( 0.92549, 0.203922, 0.0352941, 1 ) 54 | round_precision = 14 55 | 56 | [node name="shootCast" type="RayCast" parent="Camera"] 57 | enabled = true 58 | cast_to = Vector3( 0, 0, -1000 ) 59 | 60 | [node name="CollisionShape" type="CollisionShape" parent="."] 61 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.33035, 0 ) 62 | shape = SubResource( 1 ) 63 | 64 | [node name="footCast" type="RayCast" parent="." groups=[ 65 | "hlTrigger", 66 | "player", 67 | ]] 68 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.013726, 0, 0 ) 69 | enabled = true 70 | cast_to = Vector3( 0, -0.001, 0 ) 71 | 72 | [node name="footstepSound" type="AudioStreamPlayer3D" parent="."] 73 | unit_db = 10.0 74 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="gldsrc BSP Loader" 4 | description="Load BSP file maps into Godot" 5 | author="DataPlus" 6 | version="0.1" 7 | script="plugin.gd" 8 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/plugin.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends EditorPlugin 3 | 4 | 5 | var pluginDock 6 | 7 | var curSlectedNode = null 8 | 9 | func _enter_tree(): 10 | add_custom_type("GLDSRC_Map","Spatial",load("res://addons/gldsrcBSP/src/BSP_Map.gd"),null) 11 | pluginDock = load("res://addons/gldsrcBSP/pluginToolbar.tscn").instance() 12 | add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU,pluginDock) 13 | 14 | pluginDock.get_node("createMapButton").connect("pressed", self, "createMap") 15 | pluginDock.visible = false 16 | 17 | func _exit_tree(): 18 | remove_custom_type("createMapButton") 19 | remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU,pluginDock) 20 | 21 | func make_visible(visible: bool) -> void: 22 | if pluginDock: 23 | pluginDock.set_visible(visible) 24 | 25 | func handles(object): 26 | return object is GLDSRC_Map 27 | 28 | func edit(object): 29 | curSlectedNode = object 30 | 31 | func createMap(): 32 | curSlectedNode.createMap() 33 | recursiveOwn(curSlectedNode,get_tree().edited_scene_root) 34 | 35 | 36 | func recursiveOwn(node,newOwner): 37 | for i in node.get_children(): 38 | if !i.has_meta("hidden"): 39 | recursiveOwn(i,newOwner) 40 | 41 | node.owner = newOwner 42 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/pluginToolbar.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene format=2] 2 | 3 | [node name="HBoxContainer" type="HBoxContainer"] 4 | anchor_right = 1.0 5 | anchor_bottom = 1.0 6 | __meta__ = { 7 | "_edit_use_anchors_": false 8 | } 9 | 10 | [node name="createMapButton" type="Button" parent="."] 11 | margin_right = 1024.0 12 | margin_bottom = 600.0 13 | size_flags_horizontal = 3 14 | text = "Create Map" 15 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/src/BSP_Map.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Spatial 3 | class_name GLDSRC_Map 4 | signal mapLoaded 5 | signal playerSpawnSignal(dict) 6 | var file 7 | var directory = {} 8 | var spawns = [] 9 | 10 | onready var imageBuilder = get_node("ImageBuilder") 11 | onready var levelBuilder = get_node("levelBuilder") 12 | onready var entityDataParser = get_node("entityDataParser") 13 | onready var bmlLoader = get_node("bmpLoader") 14 | onready var lightmapAtlas = get_node("lightmapAtlas") 15 | var wadDict = {} 16 | #export(Array,String,FILE) var additionalWadDirs = [""] 17 | var vertices = [] 18 | var planes = [] 19 | var edges = [] 20 | var surfaces = [] 21 | var renderables = [] 22 | var renderableEdges = [] 23 | var textureInfo = [] 24 | var textureCache = {} 25 | var textures = [] 26 | var entities = [] 27 | var brushModels = [] 28 | var postFuncBrushes = [] 29 | var postPostFuncBrushes = [] 30 | var edgeToFaceIndexMap = {} 31 | var faceMeshNodes = {} 32 | var lightNodes = null 33 | var brushNodes = null 34 | var firstTick = true 35 | var loaded = false 36 | var playerSpawnSet = false 37 | var hotFaces = [] 38 | var renderModeFaces = [] 39 | var renderFaces = [] 40 | var ligthMapOffset = null 41 | var lightMap = [] 42 | var rawLightmap = [] 43 | var entityDataArr = [] 44 | export var importLightmaps = true 45 | export var optimize = true 46 | export var textureFilterSkyBox = true 47 | export var enableEntities = true 48 | export var disableSound = false 49 | export var textureLights = false 50 | 51 | var simpleCombine = true 52 | var physicsPropsDontRotate = true 53 | var playerSpawn = {"position":Vector3.ZERO,"rotation":Vector3.ZERO} 54 | var faceIndexToMaterialMap = {} 55 | var nameToPathMap = {} 56 | var materialCache = {} 57 | var textureToFacesDict = {} 58 | var modelRenderModes = {} 59 | var textureToMaterialDict = {} 60 | var skyTexture = "desert" 61 | var hlPath = null 62 | export var texturesPerMesh = 3 63 | 64 | var LUMP_NANES = [ 65 | "LUMP_ENTITES","LUMP_PLANES","LUMP_TEXTURES","LUMP_VERTICES","LUMP_VISIBILITY", 66 | "LUMP_NODES","LUMP_TEXINFO","LUMP_FACES","LUMP_LIGHTING","LLUMP_CLIPNODES","LUMP_LEAVES", 67 | "LUMP_MARKSURFACES","LUMP_EDGES", "LUMP_SURFEDGES","LUMP_MODELS","HEADER_LUMPS", 68 | ] 69 | 70 | 71 | export(String,FILE,GLOBAL) var path = "Enter path to BSP here" 72 | export var scaleFactor = 0.05 73 | export var disableTextures = false 74 | export var textureFiltering = false 75 | export var cacheMaterials = true 76 | var collisions = true 77 | export var lights = false 78 | func _ready(): 79 | 80 | if !Engine.is_editor_hint(): 81 | if !find_node("Geometry"): 82 | createMap() 83 | 84 | if get_node_or_null("spawns"): 85 | var s = get_node("spawns").get_children() 86 | if s.size() > 0: 87 | emit_signal("playerSpawnSignal",{"pos":s[0].global_transform.origin,"rot":s[0].rotation_degrees.y}) 88 | else: 89 | emit_signal("playerSpawnSignal",{"pos":Vector3.ZERO,"rot":0}) 90 | 91 | 92 | 93 | 94 | 95 | 96 | func createMap(): 97 | #print("---creating map---") 98 | levelBuilder = get_node("levelBuilder") 99 | entityDataParser = get_node("entityDataParser") 100 | imageBuilder = get_node("ImageBuilder") 101 | lightmapAtlas = get_node("lightmapAtlas") 102 | clearAllData() 103 | createSubNodes(["Lights","BrushEntities","triggers","decals","spawns"]) 104 | lightNodes = get_node("Lights") 105 | brushNodes = get_node("BrushEntities") 106 | 107 | if loadBSP() == false: 108 | print("failed to load BSP file") 109 | deleteSubNodes(["Lights","BrushEntities","triggers","decals"]) 110 | return 111 | 112 | 113 | levelBuilder.createLevel(directory,wadDict) 114 | 115 | 116 | 117 | if enableEntities == false: 118 | set_meta("done",true) 119 | return 120 | 121 | for i in entityDataArr: 122 | entityDataParser.parseEntityData2(i) 123 | 124 | 125 | entityDataParser.doRenderModes2() 126 | set_meta("done",true) 127 | loaded = true 128 | 129 | func _physics_process(delta): 130 | if loaded and !playerSpawnSet: 131 | emit_signal("playerSpawnSignal",getSpawn()) 132 | playerSpawnSet = true 133 | 134 | 135 | func loadBSP(): 136 | var a = OS.get_system_time_msecs() 137 | file = load("res://addons/gldsrcBSP/DFile.gd").new() 138 | path = path.replace("\\","/") 139 | 140 | if !file.loadFile(path): 141 | print("file not found:", path) 142 | return false 143 | 144 | var filePath = path.replace("\\","/") 145 | 146 | filePath = filePath.substr(0,filePath.find_last("/") ) 147 | filePath = filePath.substr(0,filePath.find_last("/") ) 148 | filePath = filePath + '/' 149 | 150 | 151 | directory["version"] = file.get_32u() 152 | 153 | if path.find("cstrike"): 154 | hlPath = filePath.replace("cstrike","valve") 155 | 156 | wadDict["baseDirectory"] = filePath 157 | #filePath = path.substr(0,path.find_last("/") ) 158 | for i in range(0,15): 159 | var lumpName = LUMP_NANES[i] 160 | directory[lumpName] = {} 161 | directory[lumpName]["offset"] = file.get_32u() 162 | directory[lumpName]["length"] = file.get_32u() 163 | pass 164 | 165 | #a = OS.get_system_time_msecs() 166 | parse_texinfo(directory["LUMP_TEXINFO"]) 167 | #print("texinf:",OS.get_system_time_msecs()-a) 168 | #a = OS.get_system_time_msecs() 169 | parse_texture(directory["LUMP_TEXTURES"]) 170 | #print("texture:",OS.get_system_time_msecs()-a) 171 | #a = OS.get_system_time_msecs() 172 | parse_vertices(directory["LUMP_VERTICES"]) 173 | #print("vertices:",OS.get_system_time_msecs()-a) 174 | #a = OS.get_system_time_msecs() 175 | parse_planes(directory["LUMP_PLANES"]) 176 | #print("planes:",OS.get_system_time_msecs()-a) 177 | #a = OS.get_system_time_msecs() 178 | parse_edges(directory[ "LUMP_EDGES"]) 179 | #print("edges:",OS.get_system_time_msecs()-a) 180 | #a = OS.get_system_time_msecs() 181 | parse_surfedges(directory["LUMP_SURFEDGES"]) 182 | #print("surfedges:",OS.get_system_time_msecs()-a) 183 | #a = OS.get_system_time_msecs() 184 | parseLightmap(directory["LUMP_LIGHTING"]) 185 | #print("lightmap:",OS.get_system_time_msecs()-a) 186 | #a = OS.get_system_time_msecs() 187 | parse_faces(directory["LUMP_FACES"]) 188 | #print("faces:",OS.get_system_time_msecs()-a) 189 | #a = OS.get_system_time_msecs() 190 | parse_models(directory["LUMP_MODELS"]) 191 | #print("models:",OS.get_system_time_msecs()-a) 192 | #a = OS.get_system_time_msecs() 193 | parse_entites(directory["LUMP_ENTITES"]) 194 | #print("entities:",OS.get_system_time_msecs()-a) 195 | 196 | #lightMapToImage() 197 | readMaterialSounds() 198 | #print("parse time:",OS.get_system_time_msecs()-a) 199 | return true 200 | 201 | 202 | 203 | func parse_entites(lumpDict): 204 | file.seek(lumpDict["offset"]) 205 | var allText = file.get_String(lumpDict["length"]) 206 | allText = allText.replace("}","") 207 | var entArrayTxt = allText.split("{\n",false) 208 | var entArrayToken 209 | 210 | var entDictData = [] 211 | 212 | for t in entArrayTxt: 213 | var curEntDict = {} 214 | var allLines = t.split("\n",false) 215 | for line in allLines: 216 | #var temp = line 217 | var temp2 = line.split("\"",false) 218 | #var firstQoutePos = temp.find("\"") 219 | #var secondQoutePos = temp.find("\"",firstQoutePos+1) 220 | #var thirdQoutePos = temp.find("\"",secondQoutePos+1) 221 | #var fourthQoutePos = temp.find("\"",thirdQoutePos+1) 222 | 223 | #var identifier = temp.substr(firstQoutePos+1,secondQoutePos-1) 224 | #var value = temp.substr(thirdQoutePos+1) 225 | var identifier = temp2[0] 226 | var value = temp2[2] 227 | curEntDict[identifier] = value.trim_suffix("\"") 228 | entDictData.append(curEntDict) 229 | 230 | 231 | for i in entDictData: 232 | if i.has("WAD"): 233 | entityDataParser.allWADparse(i,wadDict) 234 | else: 235 | entityDataArr.append(i) 236 | 237 | entities = entDictData 238 | 239 | 240 | 241 | func parse_vertices(lumpDict): 242 | file.seek(lumpDict["offset"]) 243 | var size = lumpDict["length"] 244 | 245 | for i in size/(4*3): 246 | var vec = file.get_Vector32() 247 | vertices.append(Vector3(-vec.x,vec.z,vec.y)*scaleFactor) 248 | 249 | 250 | 251 | func parse_planes(planeDict): 252 | file.seek(planeDict["offset"]) 253 | var size = planeDict["length"] 254 | var planeArray = [] 255 | for i in size/(5*4): 256 | var vect = file.get_Vector32() 257 | var dist = file.get_float32() 258 | var type = file.get_32u() 259 | planeArray.append({"normal":Vector3(-vect.x,vect.z,vect.y),"distance":dist,"type":type}) 260 | 261 | 262 | planes = planeArray 263 | 264 | func parse_edges(edgeDict): 265 | file.seek(edgeDict["offset"]) 266 | var size = edgeDict["length"] 267 | var edgeArray = [] 268 | 269 | for i in size/2: 270 | var a = file.get_16() 271 | var b = file.get_16() 272 | edgeArray.append([a,b]) 273 | 274 | edges = edgeArray 275 | 276 | func parse_surfedges(surfedgeDict): 277 | file.seek(surfedgeDict["offset"]) 278 | var size = surfedgeDict["length"] 279 | var surfedgeArray = [] 280 | 281 | for i in (size/4): 282 | surfedgeArray.append(file.get_32()) 283 | 284 | surfaces = surfedgeArray 285 | 286 | 287 | func parse_faces(facesDict): 288 | file.seek(facesDict["offset"]) 289 | var size = facesDict["length"] 290 | var index = 0 291 | for i in size/(12+4+4): 292 | var dict = {} 293 | var planeIndex = file.get_16() 294 | var planeSide = file.get_16() 295 | var fistEdgeIndex = file.get_32() 296 | var numFaceEdges = file.get_16() 297 | var faceTetxureInfoIdx = file.get_16() 298 | var faceEdges = [] 299 | 300 | var nStyles1 = file.get_8() 301 | var nStyles2 = file.get_8() 302 | var nStyles3 = file.get_8() 303 | var nStyles4 = file.get_8() 304 | var faceverts = [] 305 | #dict["nStyles"] = [nStyles1,nStyles2,nStyles3,nStyles4] 306 | 307 | var lightmapOffset = file.get_32() 308 | var surfEdges = [] 309 | for j in range(fistEdgeIndex,fistEdgeIndex+numFaceEdges): 310 | surfEdges.append(j) 311 | 312 | var edge 313 | 314 | #dict["origFaces"] = [index] 315 | 316 | for e in surfEdges: 317 | if surfaces[e] >= 0: 318 | edge = edges[surfaces[e]] 319 | faceverts.append(vertices[edge[0]]) 320 | 321 | 322 | if !edgeToFaceIndexMap.has(edge): 323 | edgeToFaceIndexMap[edge] = [] 324 | edgeToFaceIndexMap[edge].append(index) 325 | faceEdges.append(edge) 326 | else: 327 | edge = edges[-surfaces[e]] 328 | faceverts.append(vertices[edge[1]]) 329 | 330 | 331 | if !edgeToFaceIndexMap.has(edge): 332 | edgeToFaceIndexMap[edge] = [] 333 | edgeToFaceIndexMap[edge].append(index) 334 | faceEdges.append(edge) 335 | 336 | var texInfo = textureInfo[faceTetxureInfoIdx] 337 | var textureI = textures[texInfo["textureIndex"]] 338 | var textureName = textureI["name"] 339 | 340 | if !textureToFacesDict.has(textureName): 341 | textureToFacesDict[textureName] = [index] 342 | else: 343 | textureToFacesDict[textureName].append(index) 344 | 345 | var norm = planes[planeIndex]["normal"] 346 | if planeSide == 1: norm = -norm 347 | norm = norm.snapped(Vector3(0.0001,0.0001,0.0001)) 348 | var lightmapUV = [] 349 | var uvs = [] 350 | for v in faceverts: 351 | uvs.append(texProject(v,texInfo)) 352 | lightmapUV.append(texProject(v,texInfo)) 353 | 354 | 355 | 356 | var lImage = lightmapFunc(uvs,lightmapOffset,lightmapUV) 357 | var lightmapPos = get_node("lightmapAtlas").addToAtlas2(lImage,index) 358 | var uvOffset = Vector2(texInfo["fSShift"],texInfo["fTShift"]) 359 | var f = {} 360 | f[textureName] = {} 361 | f[textureName] = [{"verts":faceverts,"normal":norm,"texInfo":texInfo,"uv":uvs,"uvOffset":uvOffset,"lightmapUV":lightmapUV,"localLightmap":lImage,"faceIndex":index}] 362 | 363 | renderables.append(f) 364 | renderableEdges.append(faceEdges) 365 | index += 1 366 | 367 | 368 | func parse_texinfo(texinfoDict): 369 | file.seek(texinfoDict["offset"]) 370 | var size = texinfoDict["length"] 371 | var texInfoArr = [] 372 | 373 | for i in size/(4*4 + 12*2): 374 | var infoDict = {} 375 | infoDict["vS"] = file.get_Vector32()#12 376 | infoDict["fSShift"] = file.get_float32()#4 377 | infoDict["vT"]= file.get_Vector32()#12 378 | infoDict["fTShift"] = file.get_float32()#4 379 | infoDict["textureIndex"] = file.get_32()#4 380 | infoDict["flags"] = file.get_32()#4 381 | 382 | infoDict["vS"] = Vector3(-infoDict["vS"].x,infoDict["vS"].z,infoDict["vS"].y) 383 | infoDict["vT"] = Vector3(-infoDict["vT"].x,infoDict["vT"].z,infoDict["vT"].y) 384 | 385 | 386 | texInfoArr.append(infoDict) 387 | 388 | textureInfo = texInfoArr 389 | 390 | 391 | func parse_texture(textureDict): 392 | var tOffset = textureDict["offset"] 393 | file.seek(tOffset) 394 | 395 | var size = textureDict["length"] 396 | #textureDict["images"] = [] 397 | var textureImagesArr = [] 398 | var textureOffsets = [] 399 | 400 | 401 | var numberOfTextures = file.get_32() 402 | for i in numberOfTextures: 403 | textureOffsets.append(file.get_32u()+textureDict["offset"]) 404 | 405 | for i in textureOffsets: 406 | if i > file.get_len():#simple error check to prevent crash 407 | textures.append({}) 408 | continue 409 | 410 | file.seek(i) 411 | var cur = {} 412 | var fName = file.get_String(16) 413 | 414 | var w = file.get_32u() 415 | var h = file.get_32u() 416 | 417 | var mip1 = file.get_32u() 418 | var mip2 = file.get_32u() 419 | var mip3 = file.get_32u() 420 | var mip4 = file.get_32u() 421 | 422 | if mip1 == 0: 423 | textures.append({"dim":[w,h],"name":fName,"external":true}) 424 | continue 425 | 426 | var mip1sz = mip2 - mip1 427 | var mip4sz = mip1sz / 64 428 | 429 | file.seek(mip1+i) 430 | 431 | var data = [] 432 | var pallete = [] 433 | var pixSize = w*h 434 | 435 | 436 | data = file.bulkByteArr(pixSize) 437 | 438 | file.seek(mip4+i+mip4sz+2) 439 | 440 | for c in 256: 441 | var r = file.get_8() / 255.0 442 | var g = file.get_8() / 255.0 443 | var b = file.get_8() / 255.0 444 | pallete.append(Color(r,g,b,1)) 445 | 446 | textures.append({"dim":[w,h],"data":data,"palette":pallete,"name":fName}) 447 | 448 | return textures 449 | 450 | func parse_models(modelDict): 451 | var tOffset = modelDict["offset"] 452 | file.seek(tOffset) 453 | var length = modelDict["length"] 454 | for i in length/(12*3 + 4*7): 455 | 456 | var faceArr = [] 457 | var BBmin = file.get_Vector32()#12 458 | var BBmax = file.get_Vector32() 459 | var origin = file.get_Vector32() 460 | var node1 = file.get_32() 461 | var node2 = file.get_32() 462 | var node3 = file.get_32() 463 | var node4 = file.get_32() 464 | var numVisLeafs = file.get_32() 465 | var firstFaceIndex = file.get_32() 466 | var numFaces = file.get_32() 467 | 468 | BBmin = Vector3(-BBmin.x,BBmin.z,BBmin.y)*scaleFactor 469 | BBmax = Vector3(-BBmax.x,BBmax.z,BBmax.y)*scaleFactor 470 | origin = Vector3(-origin.x,origin.z,origin.y)*scaleFactor 471 | var BBabs = BBmax - BBmin 472 | BBabs = Vector3(abs(BBabs.x),abs(BBabs.y),abs(BBabs.z)) 473 | for f in numFaces: 474 | faceArr.append(f+firstFaceIndex) 475 | if !hotFaces.has(f+firstFaceIndex) and i!=0: 476 | hotFaces.append(f+firstFaceIndex) 477 | 478 | 479 | 480 | brushModels.append({"faceArr":faceArr,"BBMin":BBmin,"BBMax":BBmax,"origin": origin,"BBabs":BBabs}) 481 | 482 | func parseLightmap(lightMapDict): 483 | 484 | ligthMapOffset = lightMapDict["offset"] 485 | file.seek(lightMapDict["offset"]) 486 | var size = lightMapDict["length"] 487 | 488 | #for i in (size/3): 489 | # var r = file.get_8()/255.0 490 | # var g = file.get_8()/255.0 491 | # var b = file.get_8()/255.0 492 | # lightMap.append(Color(r,g,b)) 493 | 494 | #file.seek(lightMapDict["offset"]) 495 | rawLightmap = file.get_buffer(size) 496 | 497 | func fetchTexture(textureName,isDecal = false): 498 | 499 | if textureCache.has(textureName): 500 | return textureCache[textureName] 501 | 502 | 503 | for i in wadDict: 504 | if typeof(wadDict[i]) != TYPE_DICTIONARY: 505 | continue 506 | 507 | if wadDict[i].has(textureName): 508 | var textureFile = wadDict[i][textureName] 509 | var texture = imageBuilder.createImage(textureFile,isDecal) 510 | textureCache[textureName] = texture 511 | return texture 512 | 513 | 514 | for i in textures: 515 | if i.name == textureName: 516 | if i.has("data"): 517 | var texture = imageBuilder.createImage(null,isDecal,i) 518 | textureCache[textureName] = texture 519 | return texture 520 | 521 | 522 | print("texture not found:",textureName) 523 | # breakpoint 524 | 525 | func loadSound(fileName): 526 | var dir = path 527 | dir = dir.substr(0,dir.find_last('/')) 528 | dir = dir.substr(0,dir.find_last('/')) 529 | dir = dir + "/sound/" + fileName 530 | 531 | var stream = get_node("waveLoader").getStreamFromWAV(dir) 532 | if stream.data.size() == 0: 533 | if hlPath != null: 534 | stream = get_node("waveLoader").getStreamFromWAV(dir.replace("cstrike","valve")) 535 | if stream.data.size() == 0: 536 | print("couldn't find sound file:",fileName) 537 | return stream 538 | 539 | func createAudioPlayer3DfromName(fileName): 540 | fileName = fileName.replace("*","") 541 | if fileName.find(".wav") == -1 or disableSound: 542 | return AudioStreamPlayer3D.new() 543 | 544 | var stream : AudioStreamSample = loadSound(fileName) 545 | var player = AudioStreamPlayer3D.new() 546 | player.stream = stream 547 | return player 548 | 549 | func fetchMaterial(nameStr): 550 | var isFirstINstance = false 551 | if !materialCache.has(nameStr) or !cacheMaterials: 552 | materialCache[nameStr] = [] 553 | isFirstINstance = true 554 | var mat = SpatialMaterial.new() 555 | 556 | return {"material":mat,"isFirstInstance":isFirstINstance} 557 | 558 | return {"material":materialCache[nameStr],"isFirstInstance":isFirstINstance} 559 | 560 | func saveToMaterialCache(nameStr,mat): 561 | materialCache[nameStr] = mat 562 | 563 | func readMaterialSounds(): 564 | var dir = path 565 | dir = dir.substr(0,dir.find_last('/')) 566 | dir = dir.substr(0,dir.find_last('/')) 567 | var matPath = dir + "/sound/materials.txt" 568 | var materialFile = File.new() 569 | var result = materialFile.open(matPath,materialFile.READ) 570 | if result != 0: 571 | return 572 | 573 | var content = materialFile.get_as_text() 574 | content = content.split("\n") 575 | 576 | 577 | for line in content: 578 | if line.length() == 0: 579 | continue 580 | if line[0] == "/": 581 | continue 582 | line = line.split(" ") 583 | var matType = line[0] 584 | var textureName = line[1] 585 | textureToMaterialDict[textureName] = matType 586 | # if textures.has(textureName): 587 | # breakpoint 588 | 589 | func lightMapToImage(): 590 | return 591 | var img : Image = Image.new() 592 | 593 | var size = (directory["LUMP_LIGHTING"]["length"]/4) 594 | #print(size) 595 | var w = sqrt(size) 596 | var h = w 597 | 598 | img.create(w,h,false,Image.FORMAT_RGBF) 599 | img.lock() 600 | 601 | var count = 0 602 | for y in h: 603 | for x in w: 604 | img.set_pixel(x,y,lightMap[count]) 605 | count+=1 606 | img.create_from_data(w,h,false,Image.FORMAT_RGBF,lightMap) 607 | #img.save_png("lightmatTest.png") 608 | 609 | func createSubNodes(arr): 610 | for i in arr: 611 | var node = Spatial.new() 612 | node.name = i 613 | add_child(node) 614 | 615 | func deleteSubNodes(arr): 616 | for i in arr: 617 | if get_node(i)!= null: 618 | remove_child(get_node(i)) 619 | 620 | func clearAllData(): 621 | vertices.clear() 622 | planes.clear() 623 | edges.clear() 624 | surfaces.clear() 625 | textureInfo.clear() 626 | textureCache = {} 627 | textures.clear() 628 | entities.clear() 629 | brushModels.clear() 630 | postFuncBrushes.clear() 631 | postPostFuncBrushes.clear() 632 | edgeToFaceIndexMap = {} 633 | faceMeshNodes = {} 634 | firstTick = true 635 | playerSpawnSet = false 636 | hotFaces.clear() 637 | renderModeFaces.clear() 638 | renderFaces.clear() 639 | lightMap.clear() 640 | renderables.clear() 641 | renderableEdges.clear() 642 | 643 | 644 | func texProject(vert,texInfo): 645 | 646 | var vs = texInfo["vS"] 647 | var fShift = texInfo["fSShift"] 648 | var vt = texInfo["vT"] 649 | var tShift = texInfo["fTShift"] 650 | 651 | #var u = vert.dot(vs)#*scaleFactor 652 | #var v = vert.dot(vt)#*scaleFactor 653 | 654 | # u += fShift 655 | # v += tShift 656 | 657 | var u= vert.dot(vs)/scaleFactor 658 | var v= vert.dot(vt)/scaleFactor 659 | u += fShift 660 | v += tShift 661 | 662 | 663 | return Vector2(u,v) 664 | 665 | 666 | func texProject2(vert,texInfo): 667 | 668 | var vs = texInfo["vS"] 669 | var fShift = texInfo["fSShift"] 670 | var vt = texInfo["vT"] 671 | var tShift = texInfo["fTShift"] 672 | 673 | var u = vert.dot(vs)#*scaleFactor 674 | var v = vert.dot(vt)#*scaleFactor 675 | 676 | u += fShift 677 | v += tShift 678 | 679 | #var u= vert.dot(vs)/scaleFactor 680 | #var v= vert.dot(vt)/scaleFactor 681 | #u += fShift 682 | #v += tShift 683 | 684 | 685 | return Vector2(u,v) 686 | 687 | func lightmapFunc(vertsUV,ligthmapDataOffset,lightmapuv): 688 | 689 | var mins = Vector2(INF,INF) 690 | var maxs = Vector2(-INF,-INF) 691 | 692 | 693 | for i in vertsUV: 694 | if i.x < mins.x : mins.x = i.x 695 | if i.y < mins.y : mins.y = i.y 696 | 697 | if i.x > maxs.x : maxs.x = i.x 698 | if i.y > maxs.y : maxs.y = i.y 699 | 700 | var uvDim = maxs - mins 701 | 702 | var maxs16 = (maxs/16).ceil() 703 | var mins16 = (mins/16).floor() 704 | 705 | 706 | 707 | 708 | 709 | var lightMapDim = (maxs16 - mins16)+Vector2(1,1) 710 | 711 | var texturel = createLightMapTexture(lightMapDim,ligthmapDataOffset) 712 | 713 | 714 | 715 | #lightmapuv.resize(vertsUV.size()) 716 | for i in vertsUV.size(): 717 | lightmapuv[i] = (vertsUV[i] - mins)/ uvDim 718 | #lightmapuv[i] -= lightmapuv[i]*0.001 719 | 720 | 721 | return texturel 722 | 723 | 724 | func createLightMapTexture(dim,offset): 725 | 726 | var w = dim.x 727 | var h = dim.y 728 | #var rawLightmap = rawLightmap 729 | 730 | var image : Image = Image.new() 731 | image.create(dim.x,dim.y,false,Image.FORMAT_RGB8) 732 | var fmt = image.get_format() 733 | image.lock() 734 | var i = 0 735 | 736 | for y in h: 737 | for x in w: 738 | var index = (x+(y*w))*3 739 | var r = rawLightmap[offset + index] 740 | var g = rawLightmap[offset + index + 1] 741 | var b = rawLightmap[offset + index + 2] 742 | var color = Color8(r,g,b) 743 | 744 | image.set_pixel(x,y,color) 745 | 746 | image.unlock() 747 | #var rect = Rect2(Vector2(0.5,0.5),image.get_size()-Vector2(0.5,0.5)) 748 | #image = image.get_rect(rect) 749 | 750 | #var texture = ImageTexture.new() 751 | #texture.create_from_image(image) 752 | #texture.flags -= texture.FLAG_FILTER 753 | 754 | return image 755 | 756 | 757 | func changeLevel(mapname): 758 | clearAllData() 759 | breakpoint 760 | 761 | func getSpawn(): 762 | if get_node_or_null("spawns"): 763 | var s = get_node("spawns").get_children() 764 | if s.size() > 0: 765 | return {"pos":s[0].global_transform.origin,"rot":s[0].rotation_degrees.y} 766 | else: 767 | return {"pos":s[0].global_transform.origin,"rot":s[0].rotation_degrees.y} 768 | else: 769 | return null 770 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/src/bmpLoader.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Node 3 | 4 | 5 | var file 6 | var fileDict = {} 7 | var colorTable = [] 8 | 9 | func _ready(): 10 | set_meta("hidden",true) 11 | 12 | func getImageFromBMP(path,rotate = false): 13 | fileDict = {} 14 | colorTable = [] 15 | 16 | file = load("res://addons/gldsrcBSP/DFile.gd").new() 17 | if !file.loadFile(path): 18 | print("bmp file not found:" + path) 19 | return Image.new() 20 | 21 | fileDict["magic"] = file.get_String(2) 22 | fileDict["fileSize"] = file.get_32() 23 | fileDict["reserved"] = file.get_32() 24 | fileDict["data offset"] = file.get_32() 25 | 26 | parseInfoHeader() 27 | parseColorTable() 28 | var img = parseData(rotate) 29 | 30 | return img 31 | 32 | func createTextureFromBMP(path): 33 | var img = getImageFromBMP(path) 34 | var texture = ImageTexture.new() 35 | texture.create_from_image(img) 36 | 37 | return texture 38 | func parseInfoHeader(): 39 | fileDict["infoHeaderSize"] = file.get_32() 40 | fileDict["width"] = file.get_32() 41 | fileDict["height"] = file.get_32() 42 | fileDict["plane"] = file.get_16() 43 | fileDict["bitCount"] = file.get_16() 44 | fileDict["Compression"] = file.get_32() 45 | fileDict["ImageSize"] = file.get_32() 46 | fileDict["XpixelsPerM"] = file.get_32() 47 | fileDict["YpixelsPerM"] = file.get_32() 48 | fileDict["colorsUsed"] = file.get_32() 49 | fileDict["colorsImportant"] = file.get_32() 50 | if fileDict["colorsUsed"] == 0: 51 | fileDict["colorsUsed"] = 256 52 | print(fileDict["colorsImportant"]) 53 | func parseColorTable(): 54 | var colorTableSize = fileDict["colorsUsed"] 55 | for i in colorTableSize: 56 | var b = file.get_8() 57 | var g = file.get_8() 58 | var r = file.get_8() 59 | 60 | var _unused = file.get_8() 61 | 62 | 63 | colorTable.append(Color8(r,g,b)) 64 | 65 | 66 | func parseData(rotate): 67 | file.seek(fileDict["data offset"]) 68 | var image = Image.new() 69 | 70 | var width = fileDict["width"] 71 | var height = fileDict["height"] 72 | 73 | image.create(width,height,true,Image.FORMAT_RGB8) 74 | image.lock() 75 | 76 | for x in width: 77 | for y in height: 78 | var index = file.get_8() 79 | var color = colorTable[index] 80 | if rotate == false: 81 | image.set_pixel(y,width-1-x,color) 82 | else: 83 | image.set_pixel(width-1-x,height-y-1,color) 84 | 85 | image.unlock() 86 | return image 87 | 88 | 89 | func stitchImages(left,front,right,back,top,bottom): 90 | var panImage = Image.new() 91 | panImage.create(256*4,256*3,true,Image.FORMAT_RGB8) 92 | panImage.lock() 93 | var sourceRect = Rect2(Vector2(0,0),Vector2(256,256)) 94 | panImage.blend_rect(left,sourceRect,Vector2(0,256)) 95 | panImage.blend_rect(front,sourceRect,Vector2(256,256)) 96 | panImage.blend_rect(right,sourceRect,Vector2(512,256)) 97 | panImage.blend_rect(back,sourceRect,Vector2(768,256)) 98 | 99 | panImage.blend_rect(top,sourceRect,Vector2(256,0)) 100 | panImage.blend_rect(bottom,sourceRect,Vector2(256,512)) 101 | return panImage 102 | 103 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/src/entityDataParser.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Node 3 | 4 | var scaleFactor = 0.05 5 | #var renderModeFaces = [] 6 | var cornerPaths = {} 7 | var trackPaths = {} 8 | 9 | var postFuncBrushes = [] 10 | var postPostFuncBrushes = [] 11 | 12 | 13 | 14 | onready var parse_ambient_generic: FuncRef = funcref(self,"parseAmbientGeneric") 15 | onready var parse_breakable: FuncRef = funcref(self,"parseBreakable") 16 | onready var parse_button: FuncRef = funcref(self,"parseButton") 17 | onready var parse_decal: FuncRef = funcref(self,"parseDecal") 18 | onready var parse_door: FuncRef = funcref(self,"parseDoor") 19 | onready var parse_door_rotating: FuncRef = funcref(self,"parseDoorRotating") 20 | onready var parse_env_glow: FuncRef = funcref(self,"parseEnvGlow") 21 | onready var parse_env_laser: FuncRef = funcref(self,"parseEnvLaser") 22 | onready var parse_env_sprite: FuncRef = funcref(self,"parseEnvSprite") 23 | onready var parse_func_bomb_target: FuncRef = funcref(self,"parseFuncBombTarget") 24 | onready var parse_func_buyzone: FuncRef = funcref(self,"parseFuncBuyzone") 25 | onready var parse_func_hostage_rescue: FuncRef = funcref(self,"parseFuncHostageRescue") 26 | onready var parse_illusionary: FuncRef = funcref(self,"parseIllusionary") 27 | onready var parse_info_player_start: FuncRef = funcref(self,"parseInfoPlayerStart") 28 | onready var parse_info_node: FuncRef = funcref(self,"nullFunction") 29 | onready var parse_ladder: FuncRef = funcref(self,"parseLadder") 30 | onready var parse_light: FuncRef = funcref(self,"parseLight") 31 | onready var parse_light_spot: FuncRef = funcref(self,"parseLightSpot") 32 | onready var parse_model: FuncRef = funcref(self,"parseModel") 33 | onready var parse_monster_clip: FuncRef = funcref(self,"parseMonsterClip") 34 | onready var parse_mutli_manager: FuncRef = funcref(self,"parseMultiManager") 35 | onready var parse_npc: FuncRef = funcref(self,"parseNpc") 36 | onready var parse_path_corner: FuncRef = funcref(self,"parsePathCorner") 37 | onready var parse_path_track: FuncRef = funcref(self,"parsePathTrack") 38 | onready var parse_pushable: FuncRef = funcref(self,"parsePushable") 39 | onready var parse_render_mode: FuncRef = funcref(self,"parseRenderMode") 40 | onready var parse_rot_button: FuncRef = funcref(self,"parseRotButton") 41 | onready var parse_rotating: FuncRef = funcref(self,"parseRotating") 42 | onready var parse_target_cd_audio: FuncRef = funcref(self,"parseTargetCDAudio") 43 | onready var parse_track_train: FuncRef = funcref(self,"parseTrackTrain") 44 | onready var parse_train: FuncRef = funcref(self,"parseTrain") 45 | onready var parse_trigger_auto: FuncRef = funcref(self,"parseTriggerAuto") 46 | onready var parse_trigger_auto_save: FuncRef = funcref(self,"parseTriggerAutoSave") 47 | onready var parse_trigger_cd_audio: FuncRef = funcref(self,"parseTriggerCDAudio") 48 | onready var parse_trigger_change_level: FuncRef = funcref(self,"parseTriggerChangeLevel") 49 | onready var parse_trigger_hurt:FuncRef = funcref(self,"parseTriggerHurt") 50 | onready var parse_trigger_multiple: FuncRef = funcref(self,"parseTriggerMultiple") 51 | onready var parse_trigger_once = funcref(self,"parseTriggerOnce") 52 | onready var parse_trigger_push: FuncRef = funcref(self,"parseTriggerPush") 53 | onready var parse_trigger_relay: FuncRef = funcref(self,"parseTriggerRelay") 54 | onready var parse_trigger_teleport: FuncRef = funcref(self,"parseTriggerTeleport") 55 | onready var parse_trigger_transition: FuncRef = funcref(self,"parseTriggerTransition") 56 | onready var parse_wall: FuncRef = funcref(self,"parseWall") 57 | onready var parse_wall_toggle: FuncRef = funcref(self,"parseWallToggle") 58 | 59 | onready var funcDict = { 60 | "AMBIENT_GENERIC":parse_ambient_generic, 61 | "FUNC_BREAKABLE":parse_breakable, 62 | "FUNC_BUTTON":parse_button, 63 | "FUNC_DOOR":parse_door, 64 | "FUNC_DOOR_ROTATING":parse_door_rotating, 65 | "ENV_GLOW":parse_ambient_generic, 66 | "ENV_LASER":parse_env_laser, 67 | "ENV_SPRITE":parse_env_sprite, 68 | "FUNC_BOMB_TARGET":parse_func_bomb_target, 69 | "FUNC_BUYZONE":parse_func_buyzone, 70 | "FUNC_HOSTAGE_RESCUE":parse_func_hostage_rescue, 71 | "FUNC_ILLUSIONARY":parse_illusionary, 72 | "FUNC_PUSHABLE":parse_pushable, 73 | "INFO_PLAYER_START":parse_info_player_start, 74 | "INFO_NODE":parse_info_node, 75 | "LIGHT":parse_light, 76 | "LIGHT_SPOT":parse_light_spot, 77 | "FUNC_LADDER":parse_ladder, 78 | "FUNC_MONSTERCLIP":parse_monster_clip, 79 | "FUNC_ROTATING":parse_rotating, 80 | "MULTI_MANAGER":parse_mutli_manager, 81 | "PATH_CORNER":parse_path_corner, 82 | "PATH_TRACK":parse_path_track, 83 | "FUNC_TRACKTRAIN":parse_track_train, 84 | "FUNC_TRAIN":parse_train, 85 | "TRIGGER_AUTO":parse_trigger_auto, 86 | "TRIGGER_AUTOSAVE":parse_trigger_auto_save, 87 | "TRIGGER_CDAUDIO":parse_trigger_cd_audio, 88 | "TRIGGER_CHANGELEVEL":parse_trigger_change_level, 89 | "TRIGGER_HURT":parse_trigger_hurt, 90 | "TRIGGER_MULTIPLE":parse_trigger_multiple, 91 | "TRIGGER_ONCE":parse_trigger_once, 92 | "TRIGGER_PUSH":parse_trigger_push, 93 | "TRIGGER_RELAY":parse_trigger_relay, 94 | "TRIGGER_TELEPORT":parse_trigger_teleport, 95 | "TRIGGER_TRANSITION":parse_trigger_transition, 96 | "FUNC_WALL":parse_wall, 97 | "FUNC_WALL_TOGGLE":parse_wall_toggle 98 | } 99 | 100 | const MATERIAL = { 101 | 0: ["glass","bustglass1"], 102 | 1: ["wood","wood1"], 103 | 2: "metal", 104 | 3: "flesh", 105 | 4: "cinder block", 106 | 5: "ceiling tile", 107 | 6: "computer", 108 | 7: "unbreakable glass", 109 | 8: "rock" 110 | } 111 | 112 | const CDAUDIO = { 113 | 2: "Half-Life01.mp3", 114 | 3: "Prospero01.mp3", 115 | 4: "Half-Life12.mp3", 116 | 5: "Half-Life07.mp3", 117 | 6: "Half-Life10.mp3", 118 | 7: "Suspense01.mp3", 119 | 8: "Suspense03.mp3", 120 | 9: "Half-Life09.mp3", 121 | 10:"Half-Life02.mp3", 122 | 11:"Half-Life13.mp3", 123 | 12:"Half-Life04.mp3", 124 | 13:"Half-Life15.mp3", 125 | 14:"Half-Life14.mp3", 126 | 15:"Half-Life16.mp3", 127 | 16:"Suspense02.mp3", 128 | 17:"Half-Life03.mp3", 129 | 18:"Half-Life08.mp3", 130 | 19:"Prospero02.mp3", 131 | 20:"Half-Life05.mp3", 132 | 21:"Prospero04.mp3", 133 | 22:"Half-Life11.mp3", 134 | 23:"Half-Life06.mp3", 135 | 24:"Prospero03.mp3", 136 | 25:"Half-Life17.mp3", 137 | 26:"Prospero05.mp3", 138 | 27:"Suspense05.mp3", 139 | 28:"Suspense07.mp3" 140 | } 141 | 142 | const DOORSOUNDS = { 143 | 1: "doormove1.wav", 144 | 2: "doormove2.wav", 145 | 3: "doormove3.wav", 146 | 4: "doormove4.wav", 147 | 5: "doormove5.wav", 148 | 6: "doormove6.wav", 149 | 7: "doormove7.wav", 150 | 8: "doormove8.wav", 151 | 9: "doormove9.wav", 152 | 10: "doormove10.wav" 153 | } 154 | 155 | 156 | const LOCKSOUNDS = { 157 | 2: "button2.wav", 158 | 8: "button8.wav", 159 | 10: "button10.wav", 160 | 11: "button11.wav", 161 | 12: "latchlocked1.wav", 162 | } 163 | 164 | const BUTTONSOUNDS = { 165 | 1: "button1.wav", 166 | 2: "button2.wav", 167 | 3: "button3.wav", 168 | 4: "button4.wav", 169 | 5: "button5.wav", 170 | 6: "button6.wav", 171 | 7: "button7.wav", 172 | 8: "button8.wav", 173 | 9: "button9.wav", 174 | 10:"button10.wav", 175 | 11:"button11.wav", 176 | 14:"lightswitch2.wav" 177 | } 178 | 179 | const TRAINSOUNDS = { 180 | 1 : "plats/ttrain1.wav", 181 | 2 : "plats/ttrain2.wav", 182 | 3 : "plats/ttrain3.wav", 183 | 4 : "plats/ttrain4.wav", 184 | 5 : "plats/ttrain5.wav", 185 | 6 : "plats/ttrain6.wav", 186 | 7 : "plats/ttrain7.wav" 187 | } 188 | 189 | enum RENDERMODE { 190 | color = 1 191 | texture = 2 192 | glow = 3 193 | solid = 4 194 | additive = 5 195 | } 196 | 197 | func _ready(): 198 | set_meta("hidden",true) 199 | scaleFactor = get_parent().scaleFactor 200 | 201 | 202 | func parseEntityData2(entityDict): 203 | 204 | if entityDict.has("RENDERMODE"): 205 | parseRenderMode(entityDict) 206 | 207 | if entityDict.has("CLASSNAME"): 208 | var functionStr = entityDict["CLASSNAME"] 209 | if funcDict.has(functionStr): 210 | funcDict[functionStr].call_func(entityDict) 211 | #else: 212 | # print(functionStr) 213 | 214 | 215 | func allWADparse(entityDict,wadDict): 216 | var data = entityDict["WAD"] 217 | #data+=("DECALS.WAD") 218 | data = data.replace("\\QUIVER\\VALVE\\","") 219 | var baseDir = wadDict["baseDirectory"] 220 | var wadList = data.split(";",false) 221 | var hasDecal = false 222 | 223 | 224 | for i in wadList: 225 | if i == "DECALS.WAD": 226 | hasDecal = true 227 | 228 | i = i.replace("\\","/") 229 | i = i.substr(i.find_last("/")+1) 230 | var parsedWad = WADparse(baseDir + i.to_lower()) 231 | if parsedWad != null: 232 | wadDict[i] = parsedWad 233 | 234 | if hasDecal == false: 235 | var parsedWad = WADparse(baseDir +"decals.wad") 236 | if parsedWad != null: 237 | wadDict["DECALS.WAD"] = parsedWad 238 | 239 | if entityDict.has("SKYNAME"): 240 | #print(entityDict["SKYNAME"]) 241 | #get_parent().skyTexture = entityDict["SKYNAME"] 242 | get_parent().skyTexture = wadDict["baseDirectory"]+ "gfx/env/" +entityDict["SKYNAME"].to_lower() 243 | 244 | if entityDict.has("SOUNDS"):#is it possible to not have this entry? 245 | var soundId = int(entityDict["SOUNDS"]) 246 | if soundId > 1: 247 | var dir = get_parent().wadDict["baseDirectory"] + "media/" + CDAUDIO[soundId] 248 | var player = loadMP3asAudioPlayer(dir) 249 | player.autoplay = true 250 | get_parent().add_child(player) 251 | 252 | 253 | func WADparse(path): 254 | var file = load("res://addons/gldsrcBSP/DFile.gd").new() 255 | 256 | 257 | if file.loadFile(path) == false: 258 | if file.loadFile(path.replace("cstrike","valve")) == false: 259 | if file.loadFile(path.replace("dod","valve")) == false: 260 | if file.loadFile(guessWadPath(path)) == false: 261 | print("wad not found:",path) 262 | return null 263 | 264 | var imageDict = {} 265 | var magic = file.get_String(4) 266 | var numDirectories = file.get_32() 267 | var directoriesOffset = file.get_32() 268 | 269 | file.seek(directoriesOffset) 270 | 271 | var allOffsets = [] 272 | var textures = [] 273 | for d in numDirectories: 274 | var offset = file.get_32() 275 | #var pos = file.pos 276 | #var textureParsed = parseFile(file,offset) 277 | #if textureParsed != null: 278 | # textures.append(textureParsed) 279 | var prepos = file.pos 280 | var parsedFile = parseFile(file,offset) 281 | parsedFile["name"] 282 | imageDict[parsedFile["name"]] = parsedFile 283 | 284 | return(imageDict) 285 | 286 | 287 | func parseFile(file,offset): 288 | var fileDict = {} 289 | fileDict["offset"] = offset 290 | fileDict["diskSize"] = file.get_32() 291 | fileDict["size"] = file.get_32() 292 | var type = file.get_8() 293 | fileDict["type"] = type 294 | fileDict["compression"] = file.get_8() 295 | fileDict["file"] = file 296 | file.get_16()#padding 297 | fileDict["name"] = file.get_String(16) 298 | return(fileDict) 299 | #if type != 0x43: 300 | # return null 301 | 302 | #return parseTexture(file,fileDict["offset"],fileDict["size"]) 303 | 304 | func parseInfoPlayerStart(dict): 305 | var retDict = {} 306 | var rot = Vector3(0,0,0) 307 | retDict["position"] = textToVector3(dict["ORIGIN"])#Vector3(x,y,z)*scaleFactor 308 | var pos = retDict["position"]*scaleFactor#*get_parent().scale 309 | if !dict.has("ANGLES") and !dict.has("ANGLES"):#lets just do player 1 for now 310 | retDict["rotation"] = Vector3.ZERO 311 | 312 | if dict.has("ANGLES"): 313 | retDict["rotation"] = textToVector3(dict["ANGLES"])#= Vector3(rx,ry,rz)*scaleFactor 314 | 315 | if dict.has("ANGLE"): 316 | var rotationTXT = dict["ANGLE"] 317 | rot = int(rotationTXT) 318 | #retDict["rotation"] = Vector3(cos(rot),0,sin(rot))*scaleFactor 319 | retDict["rotation"] = Vector3(0,deg2rad(rot),0) 320 | 321 | 322 | var spawnPos = Spatial.new() 323 | spawnPos.translation = pos 324 | spawnPos.rotation = retDict["rotation"] 325 | spawnPos.name = String(get_parent().spawns.size()) 326 | get_parent().spawns.append({"pos":pos,"rot":rot}) 327 | get_parent().get_node("spawns").add_child(spawnPos) 328 | 329 | return retDict 330 | 331 | func parseLight(dict): 332 | if get_parent().lights == false: 333 | return 334 | var pos = textToVector3(dict["ORIGIN"]) 335 | var text = dict["_LIGHT"] 336 | var axis = text.split(" ") 337 | var r = 1 338 | var g = 1 339 | var b = 1 340 | var a = 1 341 | 342 | 343 | if axis.size() > 1: 344 | r = int(axis[0])/255.0 345 | g = int(axis[1])/255.0 346 | b = int(axis[2])/255.0 347 | a = 1 348 | if axis.size() >3: 349 | a = int(axis[3])/255.0 350 | 351 | r = 1 352 | g = 1 353 | b = 1 354 | var brush 355 | var light = OmniLight.new() 356 | 357 | if dict.has("SPAWNFLAGS"): 358 | light.visible = false 359 | 360 | if dict.has("TARGETNAME"): 361 | light.add_to_group(dict["TARGETNAME"],true) 362 | 363 | light.light_color = Color(r,g,b) 364 | light.translation = pos 365 | light.omni_range = 10 366 | light.omni_attenuation = 0.4 367 | light.light_energy = a*2.1 368 | light.light_indirect_energy = 4 369 | #light.shadow_enabled = true 370 | # light.light_energy = 5 371 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/light.gd") 372 | light.set_script(scriptRes) 373 | get_parent().lightNodes.add_child(light) 374 | 375 | 376 | func parseLightSpot(dict): 377 | 378 | if get_parent().lights == false: 379 | return 380 | 381 | var pos = textToVector3(dict["ORIGIN"]) 382 | var text = dict["_LIGHT"] 383 | var axis = text.split(" ") 384 | var r = 1 385 | var g = 1 386 | var b = 1 387 | var a = 1 388 | 389 | 390 | if axis.size() > 1: 391 | r = int(axis[0])/255.0 392 | g = int(axis[1])/255.0 393 | b = int(axis[2])/255.0 394 | a = 1 395 | if axis.size() >3: 396 | a = int(axis[3])/255.0 397 | 398 | 399 | var brush 400 | var light = SpotLight.new() 401 | 402 | if dict.has("SPAWNFLAGS"): 403 | light.visible = false 404 | 405 | if dict.has("TARGETNAME"): 406 | light.add_to_group(dict["TARGETNAME"],true) 407 | var pitch = 0 408 | if dict.has("PITCH"): 409 | int(dict["PITCH"]) 410 | pitch = (pitch + 90) 411 | 412 | light.light_energy = 5 413 | #light.light_color = Color(r,g,b) 414 | light.translation = pos 415 | light.spot_attenuation = 1.72 416 | light.rotation_degrees.y = pitch 417 | light.spot_range = 30 418 | #light.omni_range = scaleFactor * get_parent().lightRangeMultiplier 419 | light.light_indirect_energy = scaleFactor * get_parent().lightEnergyMultiplier 420 | 421 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/light.gd") 422 | light.set_script(scriptRes) 423 | get_parent().lightNodes.add_child(light) 424 | 425 | func textToVector3(text): 426 | var axis = text.split(" ") 427 | var rx = float(axis[0]) 428 | var ry = float(axis[1]) 429 | var rz = float(axis[2]) 430 | 431 | return Vector3(-rx,rz,ry)*scaleFactor 432 | 433 | 434 | func textToVector3i(text): 435 | var axis = text.split(" ") 436 | var rx = int(axis[0]) 437 | var ry = int(axis[1]) 438 | var rz = int(axis[2]) 439 | 440 | return Vector3(-rx,rz,ry)*scaleFactor 441 | 442 | func textToVector4i(text): 443 | var axis = text.split(" ") 444 | var rx = int(axis[0]) 445 | var ry = int(axis[1]) 446 | var rz = int(axis[2]) 447 | var ri = int(axis[3]) 448 | 449 | return Vector3(-rx,rz,ry)*scaleFactor 450 | 451 | func sortEntityBrushesIntoNodes(dict): 452 | for brush in dict: 453 | if brush["faceArr"].size() > 6: 454 | # print("brush model with more than 6 faces found") 455 | continue 456 | 457 | 458 | var targetFaces = brush["faceArr"] 459 | var faceMeshNodes = get_parent().faceMeshNodes 460 | var targetFaceNodes = [] 461 | 462 | for f in targetFaces: 463 | if f > faceMeshNodes.size(): 464 | continue 465 | 466 | targetFaceNodes.append(faceMeshNodes[f]) 467 | 468 | 469 | var brushNode = Spatial.new() 470 | brush["node"] = brushNode 471 | for i in targetFaceNodes: 472 | var target = i.get_parent() 473 | target.get_parent().remove_child(target) 474 | brushNode.add_child(target) 475 | get_parent().brushNodes.add_child(brushNode) 476 | 477 | 478 | 479 | 480 | 481 | 482 | func getModelInfoFromDict(dict): 483 | 484 | var modelIndexTxt = dict["MODEL"] 485 | modelIndexTxt = modelIndexTxt.trim_prefix("*") 486 | var modelIndex = int(modelIndexTxt) 487 | 488 | var bushModelInfo = get_parent().brushModels[modelIndex] 489 | 490 | return bushModelInfo 491 | 492 | func parseDoor(dict): 493 | 494 | var faceMeshNodes = get_parent().faceMeshNodes 495 | var bushModelInfo = getModelInfoFromDict(dict) 496 | var targetFaces = bushModelInfo["faceArr"] 497 | var targetNodeArr = [] 498 | 499 | var BBMin = bushModelInfo["BBMin"] 500 | var BBMax = bushModelInfo["BBMax"] 501 | var moveSound = 0 502 | var lockedSound = 0 503 | 504 | if dict.has("MOVESND"): moveSound = int(dict["MOVESND"]) 505 | if dict.has("LOCKED_SOUND"): lockedSound = int(dict["LOCKED_SOUND"]) 506 | 507 | #print(targetFaces) 508 | for i in targetFaces: 509 | if faceMeshNodes.has(i): 510 | if faceMeshNodes[i] != null: 511 | targetNodeArr.append(faceMeshNodes[i].get_parent().name) 512 | 513 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/func_door.gd") 514 | var doorComponent = Spatial.new() 515 | 516 | doorComponent.set_meta("targetNodePaths",targetNodeArr) 517 | doorComponent.set_meta("scaleFactor",scaleFactor) 518 | doorComponent.name = "func_door" 519 | 520 | if dict.has("TARGETNAME"): 521 | doorComponent.add_to_group(dict["TARGETNAME"],true) 522 | doorComponent.set_meta("locked",1) 523 | 524 | if dict.has("TARGET"): 525 | doorComponent.set_meta("target",dict["TARGET"]) 526 | 527 | var dimAbs = BBMax - BBMin 528 | doorComponent.translate(BBMin + 0.5*dimAbs) 529 | 530 | doorComponent.set_meta("dim",Vector3(dimAbs.x,dimAbs.y,dimAbs.z)) 531 | if dict.has("LIP"): 532 | doorComponent.set_meta("lip", int(dict["LIP"]) *scaleFactor) 533 | 534 | if dict.has("ANGLES"): 535 | var angs = textToVector3(dict["ANGLES"]) 536 | doorComponent.set_meta("angles",angs/scaleFactor) 537 | 538 | if dict.has("ANGLE"): 539 | var angle = float(dict["ANGLE"]) 540 | if angle ==-1: 541 | angle = Vector3.UP 542 | 543 | elif angle == -2: 544 | angle = Vector3.DOWN 545 | else: 546 | angle = Vector3(-cos(deg2rad(angle)),0,sin(deg2rad(angle))) 547 | 548 | 549 | doorComponent.set_meta("angle",angle) 550 | 551 | if dict.has("TARGETNAME"): 552 | doorComponent.name = dict["TARGETNAME"] 553 | 554 | if moveSound != 0: 555 | var audioPlayer = get_parent().createAudioPlayer3DfromName("doors/"+ DOORSOUNDS[moveSound]) 556 | audioPlayer.name = "moveSound" 557 | doorComponent.add_child(audioPlayer) 558 | 559 | if lockedSound != 0: 560 | var audioPlayer = get_parent().createAudioPlayer3DfromName("buttons/"+ LOCKSOUNDS[lockedSound]) 561 | audioPlayer.name = "lockedSound" 562 | doorComponent.add_child(audioPlayer) 563 | 564 | if dict.has("SPEED"): 565 | doorComponent.set_meta("speed",float(dict["SPEED"])) 566 | doorComponent.add_child(createInteractionAreaNode(bushModelInfo,3)) 567 | doorComponent.set_script(scriptRes) 568 | get_parent().get_node("BrushEntities").add_child(doorComponent) 569 | 570 | 571 | func parseBreakable(dict): 572 | 573 | var faceMeshNodes = get_parent().faceMeshNodes 574 | var brushModelInfo = getModelInfoFromDict(dict) 575 | var targetFaces = brushModelInfo["faceArr"] 576 | var targetNodeArr = [] 577 | var materialType = 0 578 | if dict.has("MATERIAL"): 579 | materialType = int(dict["MATERIAL"]) 580 | #var material = MATERIAL[int(dict["MATERIAL"])] 581 | 582 | for i in targetFaces: 583 | #if i > faceMeshNodes.size(): 584 | # continue 585 | if !faceMeshNodes.has(i): 586 | return 587 | if faceMeshNodes[i] == null: 588 | continue 589 | targetNodeArr.append(faceMeshNodes[i].get_parent().name) 590 | 591 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/func_breakable.gd") 592 | var breakableNode = Node.new() 593 | breakableNode.name = "func_breakable" 594 | 595 | if dict.has("TARGETNAME"): 596 | breakableNode.add_to_group(dict["TARGETNAME"],true) 597 | 598 | if dict.has("TARGET"): 599 | breakableNode.set_meta("targetName",dict["TARGET"]) 600 | breakableNode.set_meta("targetNodes",targetNodeArr[0]) 601 | breakableNode.set_meta("materialType",materialType) 602 | breakableNode.set_script(scriptRes) 603 | 604 | 605 | 606 | get_parent().get_node("BrushEntities").add_child(breakableNode) 607 | 608 | #breakpoint 609 | 610 | func parseButton(dict): 611 | 612 | var target = null 613 | if dict.has("TARGET"): 614 | target = dict["TARGET"] 615 | 616 | 617 | 618 | var sound = 0 619 | var bushModelInfo = getModelInfoFromDict(dict) 620 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/func_button.gd") 621 | 622 | 623 | var interactionAreaNode = createInteractionAreaNode(bushModelInfo,6) 624 | 625 | if dict.has("SOUNDS"): 626 | if dict["SOUNDS"] != "0": 627 | sound = int(dict["SOUNDS"]) 628 | if !BUTTONSOUNDS.has(sound): 629 | return 630 | var audioPlayer = get_parent().createAudioPlayer3DfromName("buttons/"+ BUTTONSOUNDS[sound]) 631 | audioPlayer.name = "sound" 632 | interactionAreaNode.add_child(audioPlayer) 633 | 634 | if dict.has("TARGETNAME"): 635 | interactionAreaNode.add_to_group(dict["TARGETNAME"],true) 636 | 637 | interactionAreaNode.translation =(bushModelInfo["BBMin"] + 0.5*(bushModelInfo["BBMax"]-bushModelInfo["BBMin"])) 638 | interactionAreaNode.name = "func_button" 639 | interactionAreaNode.set_meta("target",target) 640 | interactionAreaNode.set_script(scriptRes) 641 | 642 | get_parent().get_node("BrushEntities").add_child(interactionAreaNode) 643 | 644 | 645 | func parseRotButton(dict): 646 | 647 | var target = null 648 | var bushModelInfo = getModelInfoFromDict(dict) 649 | var targetFaces = bushModelInfo["faceArr"] 650 | var faceMeshNodes = get_parent().faceMeshNodes 651 | var targetNodeArr = [] 652 | var axis = Vector3(0,1,0) 653 | if dict.has("TARGET"): 654 | target = dict["TARGET"] 655 | 656 | var origin = Vector2.ZERO 657 | var sound = 0 658 | 659 | if dict.has("ORIGIN"): 660 | origin = textToVector3(dict["ORIGIN"]) 661 | 662 | var flags = int(dict["SPAWNFLAGS"]) 663 | if(flags & 64) >0:#x axis 664 | axis = Vector3(-1,0,0) 665 | 666 | if(flags & 128) >0:#y axis 667 | axis = Vector3(0,0,1) 668 | 669 | 670 | 671 | 672 | for i in targetFaces: 673 | if faceMeshNodes.has(i): 674 | setOrigin(faceMeshNodes[i].get_parent(),origin) 675 | targetNodeArr.append(faceMeshNodes[i].get_parent().name) 676 | 677 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/func_rot_button.gd") 678 | 679 | 680 | var interactionAreaNode = createInteractionAreaNode(bushModelInfo,3) 681 | 682 | if dict.has("SOUNDS"): 683 | if dict["SOUNDS"] != "0": 684 | sound = int(dict["SOUNDS"]) 685 | if BUTTONSOUNDS.has(sound): 686 | var audioPlayer = get_parent().createAudioPlayer3DfromName("buttons/"+ BUTTONSOUNDS[sound]) 687 | audioPlayer.name = "sound" 688 | interactionAreaNode.add_child(audioPlayer) 689 | 690 | interactionAreaNode.set_meta("targetNodePaths",targetNodeArr) 691 | interactionAreaNode.translation =(bushModelInfo["BBMin"] + 0.5*(bushModelInfo["BBMax"]-bushModelInfo["BBMin"]))+origin 692 | interactionAreaNode.name = "func_rot_button" 693 | interactionAreaNode.set_meta("target",target) 694 | interactionAreaNode.set_meta("axis",axis) 695 | interactionAreaNode.set_script(scriptRes) 696 | get_parent().get_node("BrushEntities").add_child(interactionAreaNode) 697 | 698 | func parseTriggerRelay(dict): 699 | 700 | if !dict.has("TARGET"): return #when target is not used killtarget is used so that wilil need to be implemented 701 | 702 | var position = textToVector3(dict["ORIGIN"]) 703 | var targetName = dict["TARGETNAME"] 704 | var target = dict["TARGET"] 705 | 706 | var delay = 0 707 | if dict.has("DELAY"): 708 | delay = int(dict["DELAY"]) 709 | var state = true 710 | var node = Spatial.new() 711 | 712 | if dict.has("TRIGGERSTATE"): 713 | state = dict["TRIGGERSTATE"] 714 | 715 | node.translation = position 716 | node.name = "trigger_relay" 717 | node.set_meta("state",state) 718 | node.set_meta("delay",delay) 719 | node.set_meta("target",target) 720 | node.set_meta("targetName",targetName) 721 | 722 | node.set_script(load("res://addons/gldsrcBSP/funcScripts/trigger_relay.gd")) 723 | node.add_to_group(targetName,true) 724 | get_parent().get_node("triggers").add_child(node) 725 | 726 | 727 | func parsePushable(dict): 728 | return 729 | var faceMeshNodes = get_parent().faceMeshNodes 730 | var bushModelInfo = getModelInfoFromDict(dict) 731 | var targetFaces = bushModelInfo["faceArr"] 732 | var rigidBody = RigidBody.new() 733 | var originPos = faceMeshNodes[targetFaces[0]].get_parent().translation 734 | 735 | rigidBody.translation = originPos 736 | rigidBody.can_sleep = false 737 | #rigid body (center translation) 738 | # 739 | for i in targetFaces: #for every static body of model 740 | if faceMeshNodes.has(i): 741 | 742 | var meshNode : MeshInstance = faceMeshNodes[i] 743 | var bodyNode = meshNode.get_parent() 744 | var parPos = meshNode.get_parent().translation 745 | #bodyNode.remove_child(meshNode)#we remove mesh from StaticBody 746 | var pos = bodyNode.translation 747 | for c in bodyNode.get_children(): 748 | c.get_parent().remove_child(c) 749 | if c.get_class() != "MeshInstance": 750 | c.queue_free() 751 | bodyNode.queue_free() 752 | 753 | 754 | rigidBody.add_child(meshNode)#we add mesh to rigidBody 755 | meshNode.create_convex_collision() 756 | 757 | var collisionShape = meshNode.get_child(0).get_child(0) 758 | 759 | meshNode.translation = parPos - originPos 760 | collisionShape.translation = parPos - originPos 761 | 762 | collisionShape.get_parent().remove_child(collisionShape) 763 | rigidBody.add_child(collisionShape) 764 | 765 | if get_parent().physicsPropsDontRotate: 766 | rigidBody.axis_lock_angular_x = true 767 | rigidBody.axis_lock_angular_y = true 768 | rigidBody.axis_lock_angular_z = true 769 | 770 | #rigidBody.translation = pos 771 | rigidBody.gravity_scale = 10 772 | get_parent().add_child(rigidBody) 773 | 774 | 775 | rigidBody.translation.y += scaleFactor 776 | rigidBody.name = "func_pushable" 777 | #get_parent().add_child(rigidBody) 778 | 779 | func parseDoorRotating(dict): 780 | var faceMeshNodes = get_parent().faceMeshNodes 781 | var bushModelInfo = getModelInfoFromDict(dict) 782 | var targetFaces = bushModelInfo["faceArr"] 783 | var targetNodeArr = [] 784 | var rotAmount = int(dict["DISTANCE"]) 785 | var BBMin = (bushModelInfo["BBMin"]) 786 | var BBMax = (bushModelInfo["BBMax"]) 787 | var origin = Vector3.ZERO 788 | var axis = Vector3(0,1,0) 789 | var initialRot = Vector3(0,0,0) 790 | 791 | #print("door target face:", targetFaces) 792 | var moveSound = 0 793 | if dict.has("MOVESND"): 794 | moveSound = int(dict["MOVESND"]) 795 | 796 | 797 | 798 | if !dict.has("ORIGIN"): 799 | #print("func_door_rotating has no origin skipping...") 800 | return 801 | origin = textToVector3(dict["ORIGIN"]) 802 | 803 | 804 | 805 | bushModelInfo["BBMax"] 806 | #print(targetFaces) 807 | for i in targetFaces: 808 | if faceMeshNodes.has(i): 809 | setOrigin(faceMeshNodes[i].get_parent(),origin) 810 | targetNodeArr.append(faceMeshNodes[i].get_parent().name) 811 | 812 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/func_door_rotating.gd") 813 | var doorComponent = Spatial.new() 814 | var uniqueParents = getUniqeParents(targetNodeArr) 815 | 816 | 817 | if moveSound != 0: 818 | var audioPlayer : AudioStreamPlayer3D = get_parent().createAudioPlayer3DfromName("doors/" + DOORSOUNDS[moveSound]) 819 | audioPlayer.name = "moveSound" 820 | audioPlayer.unit_db = 10 821 | doorComponent.add_child(audioPlayer) 822 | 823 | doorComponent.set_meta("targetNodePaths",targetNodeArr) 824 | doorComponent.set_meta("scaleFactor",scaleFactor) 825 | doorComponent.set_meta("origin",origin) 826 | doorComponent.set_meta("rotAmount",rotAmount) 827 | doorComponent.set_meta("initialRot",initialRot) 828 | 829 | doorComponent.set_meta("rotDir",1) 830 | doorComponent.name = "func_door_rotating" 831 | if dict.has("SPAWNFLAGS"): 832 | var flags = int(dict["SPAWNFLAGS"]) 833 | 834 | if (flags & (1 << 0)) > 0: 835 | pass 836 | #print("startsOpen") 837 | 838 | if (flags & (1 << 1)) > 0: 839 | doorComponent.set_meta("rotDir",-1) 840 | #print("reverseDir") 841 | 842 | if (flags & (1 << 2)) > 0: 843 | pass 844 | #print("dont link") 845 | 846 | if (flags & (1 << 3)) > 0: 847 | pass 848 | #print("passable") 849 | 850 | if (flags & (1 << 4)) > 0: 851 | pass 852 | #print("one way") 853 | 854 | if (flags & (1 << 5)) > 0: 855 | pass 856 | #print("toggle") 857 | 858 | 859 | if(flags & (1 << 7 )) > 0: 860 | #print("y axis") 861 | #initialRot = Vector3(90,0,0) 862 | axis = Vector3(0,0,1) 863 | 864 | if (flags & (1 << 6)) > 0: 865 | #print("x axis") 866 | axis = Vector3(-1,0,0) 867 | 868 | if(flags & (1 << 8)) > 0: 869 | #print("use oonly") 870 | pass 871 | 872 | doorComponent.set_meta("axis",axis) 873 | 874 | if dict.has("TARGETNAME"): 875 | doorComponent.add_to_group(dict["TARGETNAME"],true) 876 | 877 | var dimAbs = BBMax - BBMin 878 | doorComponent.translate(BBMin + 0.5*dimAbs) 879 | 880 | doorComponent.set_meta("dim",Vector3(dimAbs.x,dimAbs.y,dimAbs.z)) 881 | if dict.has("LIP"): 882 | doorComponent.set_meta("lip", int(dict["LIP"]) *scaleFactor) 883 | 884 | if dict.has("ANGLES"): 885 | var angs = textToVector3i(dict["ANGLES"]) 886 | 887 | doorComponent.set_meta("angles",angs/scaleFactor) 888 | var interactionAreaNode = createInteractionAreaNode(bushModelInfo,3) 889 | interactionAreaNode.translation = origin 890 | doorComponent.add_child(interactionAreaNode) 891 | doorComponent.set_script(scriptRes) 892 | get_parent().get_node("BrushEntities").add_child(doorComponent) 893 | 894 | 895 | func parseRotating(dict): 896 | 897 | var faceMeshNodes = get_parent().faceMeshNodes 898 | var bushModelInfo = getModelInfoFromDict(dict) 899 | var targetFaces = bushModelInfo["faceArr"] 900 | var targetNodeArr = [] 901 | var BBMin = (bushModelInfo["BBMin"]) 902 | var BBMax = (bushModelInfo["BBMax"]) 903 | var origin = Vector3.ZERO 904 | var flags = 0 905 | var axis = Vector3(0,1,0) 906 | var collisions = true 907 | if dict.has("SPAWNFLAGS"): 908 | flags = int(dict["SPAWNFLAGS"]) 909 | 910 | if (flags & (1 << 2)) > 0 or (flags & (1 << 3)) > 0: 911 | axis = Vector3.ZERO 912 | 913 | if(flags & (1 << 2 )) > 0: 914 | axis += Vector3(1,0,0) 915 | 916 | if(flags & (1 << 3)) > 0: 917 | axis += Vector3(0,0,1) 918 | 919 | if(flags & (1 << 6)) >0: 920 | collisions = false 921 | #deleteModelCollision(bushModelInfo) 922 | #for i in bushModelInfo["faceArr"]: 923 | # print(get_parent().faces[i]) 924 | 925 | 926 | 927 | 928 | if !dict.has("ORIGIN"): 929 | print("func_door_rotating has no origin skipping...") 930 | return 931 | origin = textToVector3(dict["ORIGIN"]) 932 | 933 | 934 | bushModelInfo["BBMax"] 935 | for i in targetFaces: 936 | if faceMeshNodes.has(i): 937 | setOrigin(faceMeshNodes[i].get_parent(),origin) 938 | 939 | targetNodeArr.append(faceMeshNodes[i].get_parent().name) 940 | 941 | 942 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/func_rotating.gd") 943 | var doorComponent = Spatial.new() 944 | var uniqueParents = getUniqeParents(targetNodeArr) 945 | 946 | doorComponent.set_meta("targetNodePaths",targetNodeArr) 947 | doorComponent.set_meta("scaleFactor",scaleFactor) 948 | doorComponent.set_meta("origin",origin) 949 | doorComponent.set_meta("axis",axis) 950 | doorComponent.set_meta("collision",collisions) 951 | var dimAbs = BBMax - BBMin 952 | doorComponent.translate(BBMin + 0.5*dimAbs) 953 | 954 | doorComponent.set_meta("dim",Vector3(dimAbs.x,dimAbs.y,dimAbs.z)) 955 | 956 | 957 | doorComponent.set_script(scriptRes) 958 | get_parent().get_node("BrushEntities").add_child(doorComponent) 959 | 960 | 961 | 962 | 963 | 964 | 965 | 966 | func setOrigin(node,origin): 967 | for c in node.get_children(): 968 | if "translation" in c: 969 | c.translation = node.translation 970 | 971 | node.translation = origin 972 | 973 | 974 | func parseWall(dict): 975 | pass 976 | #var faceMeshNodes = get_parent().faceMeshNodes 977 | #var bushModelInfo = getModelInfoFromDict(dict) 978 | #var targetFaces = bushModelInfo["faceArr"] 979 | #var targetNodeArr = [] 980 | 981 | #var amount = dict["RENDERAMT"] 982 | 983 | #for i in targetFaces: 984 | #targetNodeArr.append(faceMeshNodes[i]) 985 | # var meshNode = faceMeshNodes[i] 986 | # var mat = SpatialMaterial.new() godot glitch 987 | 988 | func parseDecal(dict): 989 | 990 | var sprite = load("res://addons/gldsrcBSP/funcScripts/decal.tscn").instance() 991 | var texture = get_parent().fetchTexture(dict["TEXTURE"],true) 992 | sprite.name = dict["TEXTURE"] 993 | sprite.scale *= scaleFactor * 100 994 | sprite.texture = texture 995 | sprite.translation = textToVector3(dict["ORIGIN"]) 996 | 997 | #var contactFinder = load("res://addons/gldsrcBSP/funcScripts/decal.tscn").instance() 998 | 999 | #sprite.add_child(contactFinder) 1000 | get_parent().get_node("decals").add_child(sprite) 1001 | #breakpoint 1002 | 1003 | func parseTriggerOnce(dict): 1004 | var modelInfo = getModelInfoFromDict(dict) 1005 | 1006 | 1007 | 1008 | var dimAbs = modelInfo["BBMax"] - modelInfo["BBMin"] 1009 | dimAbs = Vector3(abs(dimAbs.x),abs(dimAbs.y),abs(dimAbs.z)) 1010 | var interactionBox = createInteractionAreaNode(modelInfo) 1011 | interactionBox.translation = modelInfo["BBMin"]+ (modelInfo["BBMax"] - modelInfo["BBMin"])*0.5 1012 | 1013 | 1014 | 1015 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/trigger.gd") 1016 | 1017 | if dict.has("TARGET"): 1018 | interactionBox.set_meta("target",dict["TARGET"]) 1019 | 1020 | interactionBox.set_meta("trigger_once",true) 1021 | interactionBox.set_script(scriptRes) 1022 | 1023 | get_parent().get_node("triggers").add_child(interactionBox) 1024 | deleteModelNode(modelInfo) 1025 | 1026 | 1027 | 1028 | 1029 | func parseTriggerTeleport(dict): 1030 | var modelInfo = getModelInfoFromDict(dict) 1031 | 1032 | 1033 | 1034 | var dimAbs = modelInfo["BBMax"] - modelInfo["BBMin"] 1035 | dimAbs = Vector3(abs(dimAbs.x),abs(dimAbs.y),abs(dimAbs.z)) 1036 | var interactionBox = createInteractionAreaNode(modelInfo) 1037 | interactionBox.translation = modelInfo["BBMin"]+ (modelInfo["BBMax"] - modelInfo["BBMin"])*0.5 1038 | 1039 | 1040 | 1041 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/trigger_teleport.gd") 1042 | 1043 | if dict.has("TARGET"): 1044 | interactionBox.set_meta("target",dict["TARGET"]) 1045 | 1046 | interactionBox.set_script(scriptRes) 1047 | 1048 | get_parent().get_node("triggers").add_child(interactionBox) 1049 | deleteModelNode(modelInfo) 1050 | 1051 | 1052 | func parseTriggerMultiple(dict): 1053 | 1054 | var modelInfo = getModelInfoFromDict(dict) 1055 | 1056 | 1057 | 1058 | var dimAbs = modelInfo["BBMax"] - modelInfo["BBMin"] 1059 | dimAbs = Vector3(abs(dimAbs.x),abs(dimAbs.y),abs(dimAbs.z)) 1060 | var interactionBox = createInteractionAreaNode(modelInfo) 1061 | interactionBox.translation = modelInfo["BBMin"]+ (modelInfo["BBMax"] - modelInfo["BBMin"])*0.5 1062 | 1063 | 1064 | 1065 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/trigger.gd") 1066 | 1067 | if dict.has("TARGET"): 1068 | interactionBox.set_meta("target",dict["TARGET"]) 1069 | 1070 | interactionBox.set_meta("trigger_once",false) 1071 | interactionBox.set_script(scriptRes) 1072 | 1073 | get_parent().get_node("triggers").add_child(interactionBox) 1074 | deleteModelNode(modelInfo) 1075 | 1076 | 1077 | func parseTriggerHurt(dict): 1078 | 1079 | var modelInfo = getModelInfoFromDict(dict) 1080 | var dimAbs = modelInfo["BBMax"] - modelInfo["BBMin"] 1081 | dimAbs = Vector3(abs(dimAbs.x),abs(dimAbs.y),abs(dimAbs.z)) 1082 | var interactionBox = createInteractionAreaNode(modelInfo) 1083 | interactionBox.translation = modelInfo["BBMin"]+ (modelInfo["BBMax"] - modelInfo["BBMin"])*0.5 1084 | 1085 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/trigger.gd") 1086 | 1087 | if dict.has("TARGET"): 1088 | interactionBox.set_meta("target",dict["TARGET"]) 1089 | 1090 | interactionBox.set_meta("trigger_once",false) 1091 | interactionBox.set_script(scriptRes) 1092 | 1093 | get_parent().get_node("triggers").add_child(interactionBox) 1094 | deleteModelNode(modelInfo) 1095 | 1096 | func parseTriggerTransition(dict): 1097 | 1098 | var modelInfo = getModelInfoFromDict(dict) 1099 | var interactionBox = createInteractionAreaNode(modelInfo) 1100 | interactionBox.translation = modelInfo["BBMin"]+ (modelInfo["BBMax"] - modelInfo["BBMin"])*0.5 1101 | 1102 | 1103 | get_parent().get_node("triggers").add_child(interactionBox) 1104 | deleteModelNode(modelInfo) 1105 | 1106 | 1107 | func parseLadder(dict): 1108 | var modelInfo = getModelInfoFromDict(dict) 1109 | var interactionBox = createInteractionAreaNode(modelInfo,3) 1110 | interactionBox.translation = modelInfo["BBMin"]+ (modelInfo["BBMax"] - modelInfo["BBMin"])*0.5 1111 | interactionBox.name = "ladder" 1112 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/func_ladder.gd") 1113 | interactionBox.set_script(scriptRes) 1114 | 1115 | get_parent().get_node("triggers").add_child(interactionBox) 1116 | 1117 | 1118 | deleteModelNode(modelInfo) 1119 | 1120 | func parseTriggerPush(dict): 1121 | var modelInfo = getModelInfoFromDict(dict) 1122 | var interactionBox = createInteractionAreaNode(modelInfo,3) 1123 | interactionBox.translation = modelInfo["BBMin"]+ (modelInfo["BBMax"] - modelInfo["BBMin"])*0.5 1124 | interactionBox.name = "ladder" 1125 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/trigger_push.gd") 1126 | interactionBox.set_script(scriptRes) 1127 | 1128 | get_parent().get_node("triggers").add_child(interactionBox) 1129 | 1130 | 1131 | deleteModelNode(modelInfo) 1132 | 1133 | func parseTriggerChangeLevel(dict): 1134 | 1135 | var modelInfo = getModelInfoFromDict(dict) 1136 | var interactionBox = createInteractionAreaNode(modelInfo) 1137 | interactionBox.translation = modelInfo["BBMin"]+ (modelInfo["BBMax"] - modelInfo["BBMin"])*0.5 1138 | 1139 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/trigger_changelevel.gd") 1140 | interactionBox.set_meta("mapName",dict["MAP"]) 1141 | interactionBox.set_script(scriptRes) 1142 | get_parent().get_node("triggers").add_child(interactionBox) 1143 | 1144 | deleteModelNode(modelInfo) 1145 | 1146 | func parseTriggerAuto(dict): 1147 | 1148 | 1149 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/trigger_auto.gd") 1150 | 1151 | 1152 | 1153 | var node = Node.new() 1154 | 1155 | if dict.has("TARGET"): 1156 | node.set_meta("target",dict["TARGET"]) 1157 | 1158 | node.name = "trigger_auto" 1159 | var delay = 0 1160 | 1161 | if dict.has("DELAY"): 1162 | delay = dict["DELAY"] 1163 | 1164 | node.set_meta("delay",delay) 1165 | node.set_script(scriptRes) 1166 | get_parent().get_node("triggers").add_child(node) 1167 | 1168 | func parseTriggerAutoSave(dict): 1169 | 1170 | var modelInfo = getModelInfoFromDict(dict) 1171 | var interactionBox = createInteractionAreaNode(modelInfo) 1172 | interactionBox.translation = modelInfo["BBMin"]+ (modelInfo["BBMax"] - modelInfo["BBMin"])*0.5 1173 | interactionBox.name = "funcAutoSave" 1174 | get_parent().get_node("triggers").add_child(interactionBox) 1175 | deleteModelNode(modelInfo) 1176 | 1177 | func parseWallToggle(dict): 1178 | createInteractionBoxAndDeleteBrushModel(dict,"triggers","func_wall_toggle") 1179 | func parseMonsterClip(dict): 1180 | createInteractionBoxAndDeleteBrushModel(dict,"triggers","func_monster_clip") 1181 | func parseFuncBuyzone(dict): 1182 | createInteractionBoxAndDeleteBrushModel(dict,"triggers","func_buyzone") 1183 | 1184 | 1185 | func parseFuncBombTarget(dict): 1186 | createInteractionBoxAndDeleteBrushModel(dict,"triggers","func_bomb_target") 1187 | 1188 | func parseFuncHostageRescue(dict): 1189 | createInteractionBoxAndDeleteBrushModel(dict,"triggers","func_hostage_rescure") 1190 | 1191 | 1192 | func parseTriggerCDAudio(dict): 1193 | var modelInfo = getModelInfoFromDict(dict) 1194 | var interactionBox = createInteractionAreaNode(modelInfo) 1195 | interactionBox.translation = modelInfo["BBMin"]+ (modelInfo["BBMax"] - modelInfo["BBMin"])*0.5 1196 | var audioId = int(dict["HEALTH"]) 1197 | if audioId <= 1: 1198 | return 1199 | 1200 | var file = File.new() 1201 | var dir = get_parent().wadDict["baseDirectory"] + "media/" 1202 | dir = dir + CDAUDIO[int(dict["HEALTH"])] 1203 | var player = loadMP3asAudioPlayer(dir) 1204 | player.set_script(load("res://addons/gldsrcBSP/funcScripts/cdaudio.gd")) 1205 | var id = String(randi()) 1206 | get_parent().add_child(player) 1207 | player.add_to_group(id,true) 1208 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/trigger.gd") 1209 | interactionBox.set_meta("target",id) 1210 | interactionBox.set_meta("trigger_once",true) 1211 | interactionBox.set_script(scriptRes) 1212 | 1213 | get_parent().get_node("triggers").add_child(interactionBox) 1214 | deleteModelNode(modelInfo) 1215 | 1216 | func parseTargetCDAudio(dict): 1217 | var file = File.new() 1218 | var dir = get_parent().wadDict["baseDirectory"] + "media/" 1219 | dir = dir + CDAUDIO[int(dict["HEALTH"])] 1220 | 1221 | var audioPlayer = loadMP3asAudioPlayer(dir) 1222 | audioPlayer.autoplay = true 1223 | 1224 | 1225 | get_parent().add_child(audioPlayer) 1226 | 1227 | func doesFileExist(path): 1228 | var fExist= File.new() 1229 | var doesExist = fExist.file_exists(path) 1230 | fExist.close() 1231 | return doesExist 1232 | 1233 | 1234 | func parseEnvSprite(dict): 1235 | var spriteName = dict["MODEL"].to_lower() 1236 | var path = get_parent().wadDict["baseDirectory"] + spriteName 1237 | var renderMode = 3 1238 | if dict.has("RENDERMODE"): 1239 | renderMode = int(dict["RENDERMODE"]) 1240 | 1241 | if !doesFileExist(path): path = path.replace("cstrike","valve") 1242 | if !doesFileExist(path): return 1243 | 1244 | if path.split(".")[1] == "mdl": 1245 | print("model passed into env_sprite skipping...") 1246 | return 1247 | 1248 | var img = get_parent().imageBuilder.createTextureFromSpr(path) 1249 | var sprite : Sprite3D = Sprite3D.new() 1250 | 1251 | if dict.has("FRAMERATE"): img.fps = int(dict["FRAMERATE"]) 1252 | sprite.scale *= 100*scaleFactor 1253 | sprite.billboard = SpatialMaterial.BILLBOARD_ENABLED 1254 | sprite.texture = img 1255 | sprite.translation = textToVector3(dict["ORIGIN"]) 1256 | sprite.name = spriteName 1257 | 1258 | if renderMode == 3 or renderMode == 5: 1259 | var mat = SpatialMaterial.new() 1260 | mat.params_blend_mode = SpatialMaterial.BLEND_MODE_ADD 1261 | mat.albedo_texture = img 1262 | mat.flags_unshaded = true 1263 | mat.flags_do_not_receive_shadows = true 1264 | mat.params_billboard_mode = SpatialMaterial.BILLBOARD_ENABLED 1265 | mat.params_billboard_keep_scale = true 1266 | sprite.material_override = mat 1267 | 1268 | get_parent().add_child(sprite) 1269 | 1270 | 1271 | func parseEnvGlow(dict): 1272 | var spriteName = dict["MODEL"].to_lower() 1273 | var path = get_parent().wadDict["baseDirectory"] + spriteName 1274 | var renderMode = int(dict["RENDERMODE"]) 1275 | 1276 | if !doesFileExist(path): path = path.replace("cstrike","valve") 1277 | if !doesFileExist(path): return 1278 | 1279 | 1280 | var img = get_parent().imageBuilder.createTextureFromSpr(path) 1281 | var sprite : Sprite3D = Sprite3D.new() 1282 | 1283 | sprite.scale *= 100*scaleFactor 1284 | sprite.billboard = SpatialMaterial.BILLBOARD_ENABLED 1285 | sprite.texture = img 1286 | sprite.translation = textToVector3(dict["ORIGIN"]) 1287 | sprite.name = spriteName 1288 | 1289 | if renderMode == 3 or renderMode == 5: 1290 | var mat = SpatialMaterial.new() 1291 | mat.params_blend_mode = SpatialMaterial.BLEND_MODE_ADD 1292 | mat.albedo_texture = img 1293 | mat.flags_unshaded = true 1294 | mat.flags_do_not_receive_shadows = true 1295 | mat.params_billboard_mode = SpatialMaterial.BILLBOARD_ENABLED 1296 | mat.params_billboard_keep_scale = true 1297 | sprite.material_override = mat 1298 | 1299 | get_parent().add_child(sprite) 1300 | 1301 | 1302 | func parseEnvLaser(dict): 1303 | var target 1304 | var targetName = dict["LASERTARGET"] 1305 | 1306 | 1307 | var spriteName = dict["TEXTURE"].to_lower() 1308 | var path = get_parent().wadDict["baseDirectory"] + spriteName 1309 | var img = get_parent().imageBuilder.createTextureFromSpr(path) 1310 | var sprite = Sprite3D.new() 1311 | 1312 | sprite.set_meta("target",targetName) 1313 | var targetNodes = get_tree().get_nodes_in_group(targetName) 1314 | if targetNodes.size() == 0: 1315 | return 1316 | var targetNode = get_tree().get_nodes_in_group(targetName)[0] 1317 | 1318 | sprite.scale *= scaleFactor 1319 | sprite.billboard = SpatialMaterial.BILLBOARD_ENABLED 1320 | sprite.texture = img 1321 | sprite.translation = textToVector3(dict["ORIGIN"]) 1322 | sprite.name = spriteName 1323 | 1324 | #draw.drawLine(sprite.translation,targetNode.translation) 1325 | 1326 | var script = load("res://addons/gldsrcBSP/funcScripts/env_laser.gd") 1327 | sprite.set_script(script) 1328 | get_parent().add_child(sprite) 1329 | #ima 1330 | 1331 | func getUniqeParents(targetNodes): 1332 | var uniqueParents = [] 1333 | for i in targetNodes: 1334 | var parent = get_parent().get_path() 1335 | if !uniqueParents.has(parent): 1336 | uniqueParents.append(parent) 1337 | 1338 | return uniqueParents 1339 | 1340 | 1341 | func createInteractionAreaNode(model,growMargin = 0,nameStr ="interactionBox"): 1342 | var areaNode = Area.new() 1343 | var collisionNode = CollisionShape.new() 1344 | var shapeNode = BoxShape.new() 1345 | 1346 | var BBMin = model["BBMin"] 1347 | var BBMax = model["BBMax"] 1348 | 1349 | var dim = BBMax - BBMin 1350 | dim/=2 1351 | dim = Vector3(abs(dim.x),abs(dim.y),abs(dim.z)) 1352 | dim += Vector3(1,1,1)*scaleFactor*growMargin#box will be x units larger than object in all dimensions 1353 | 1354 | shapeNode.extents = dim 1355 | collisionNode.shape = shapeNode 1356 | areaNode.add_child(collisionNode) 1357 | areaNode.name = nameStr 1358 | 1359 | return areaNode 1360 | 1361 | 1362 | 1363 | 1364 | func parseRenderMode(dict): 1365 | 1366 | if dict["CLASSNAME"] == "LIGHT": 1367 | print("unimplimented light render mode") 1368 | return 1369 | 1370 | var mode = int(dict["RENDERMODE"]) 1371 | 1372 | if dict["CLASSNAME"] == "ENV_RENDER": 1373 | return 1374 | 1375 | if mode == 0: 1376 | return 1377 | if mode != 111111: 1378 | if !dict.has("MODEL"): 1379 | return 1380 | 1381 | 1382 | var model = dict["MODEL"] 1383 | model = model.trim_prefix("*") 1384 | 1385 | 1386 | if !model.is_valid_integer(): 1387 | return 1388 | 1389 | var amount = 255 1390 | var color = 0 1391 | if dict.has("RENDERAMT"): 1392 | amount = int(dict["RENDERAMT"])/255.0 1393 | 1394 | 1395 | if dict.has("RENDERCOLOR"): 1396 | if dict["RENDERCOLOR"] != "0": 1397 | color = dict["RENDERCOLOR"]#/255 1398 | color = color.split(" ") 1399 | var cx = int(color[0]) 1400 | var cy = int(color[1]) 1401 | var cz = int(color[2]) 1402 | color = Color8(int(cx),int(cy),int(cz)) 1403 | var faces = get_parent().brushModels[int(model)]["faceArr"] 1404 | 1405 | get_parent().renderModeFaces.append({"MODEL":model,"renderMode":mode,"RENDERAMT":amount,"RENDERCOLOR":color}) 1406 | get_parent().modelRenderModes[model] = {"renderMode":mode,"amount":amount,"renderColor":color} 1407 | #for f in faces: 1408 | # get_parent().renderFaces[string(f)] = {"renderMode":mode,"amount":amount} 1409 | 1410 | func doRenderModes2(): 1411 | if get_parent().disableTextures: 1412 | return 1413 | 1414 | var t = get_parent().modelRenderModes 1415 | for m in get_parent().modelRenderModes: 1416 | 1417 | var brushModelInfo = get_parent().brushModels[int(m)] 1418 | var faceMeshNodes = get_parent().faceMeshNodes 1419 | 1420 | for f in brushModelInfo["faceArr"]: 1421 | if faceMeshNodes.has(f): 1422 | var meshNode = faceMeshNodes[f] 1423 | for matNum in meshNode.get_surface_material_count(): 1424 | var mat = meshNode.get_active_material(matNum) 1425 | var newMat = mat.duplicate() 1426 | applyRenderToMat(get_parent().modelRenderModes[m],newMat) 1427 | 1428 | meshNode.set_surface_material(matNum,newMat) 1429 | 1430 | func applyRenderToMat(info,mat): 1431 | var renderMode = info["renderMode"] 1432 | var renderColor = info["renderColor"] 1433 | var renderAmt = info["amount"] 1434 | 1435 | if renderMode == RENDERMODE.color: 1436 | mat.albedo_texture = null 1437 | mat.albedo_color = renderColor 1438 | mat.albedo_color.a = renderAmt 1439 | 1440 | if renderMode == RENDERMODE.texture: 1441 | mat.flags_transparent = true 1442 | mat.albedo_color.a = renderAmt 1443 | 1444 | if renderMode== RENDERMODE.solid: 1445 | mat.flags_transparent = true 1446 | 1447 | 1448 | if renderMode == RENDERMODE.additive: 1449 | mat.albedo_color.a = renderAmt 1450 | mat.params_blend_mode = mat.BLEND_MODE_ADD 1451 | 1452 | if renderMode == RENDERMODE.glow: 1453 | mat.albedo_color.a = renderAmt 1454 | mat.params_blend_mode = mat.BLEND_MODE_ADD 1455 | #breakpoint 1456 | 1457 | 1458 | func parseMultiManager(dict): 1459 | var targetGroups = [] 1460 | for i in dict.keys(): 1461 | if i != "TARGETNAME" and i != "CLASSNAME" and i!= "ORIGIN": 1462 | targetGroups.append({"name":i,"delay":dict[i]}) 1463 | 1464 | 1465 | var node = Node.new() 1466 | 1467 | 1468 | if dict.has("TARGETNAME"): 1469 | node.add_to_group(dict["TARGETNAME"],true) 1470 | 1471 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/multi_manager.gd") 1472 | node.name = dict["TARGETNAME"] 1473 | node.set_meta("targetGroups",targetGroups) 1474 | node.set_script(scriptRes) 1475 | get_parent().get_node("triggers").add_child(node) 1476 | 1477 | 1478 | func parsePathCorner(dict): 1479 | var node = Position3D.new() 1480 | node.translation = textToVector3(dict["ORIGIN"]) 1481 | node.name = dict["TARGETNAME"] 1482 | if dict.has("TARGET"): 1483 | node.set_meta("target",dict["TARGET"]) 1484 | cornerPaths[node.name] = dict["TARGET"] 1485 | else: 1486 | cornerPaths[node.name] = null 1487 | 1488 | if dict.has("MESSAGE"): 1489 | node.set_meta("trigger",dict["MESSAGE"]) 1490 | 1491 | get_parent().add_child(node) 1492 | 1493 | func parsePathTrack(dict): 1494 | var node = Position3D.new() 1495 | node.translation = textToVector3(dict["ORIGIN"]) 1496 | node.name = dict["TARGETNAME"] 1497 | if dict.has("TARGET"): 1498 | node.set_meta("target",dict["TARGET"]) 1499 | trackPaths[node.name] = dict["TARGET"] 1500 | else: 1501 | trackPaths[node.name] = null 1502 | 1503 | if dict.has("MESSAGE"): 1504 | node.set_meta("trigger",dict["MESSAGE"]) 1505 | get_parent().add_child(node) 1506 | 1507 | 1508 | func parseTrain(dict): 1509 | 1510 | var faceMeshNodes = get_parent().faceMeshNodes 1511 | var brushModelInfo = getModelInfoFromDict(dict) 1512 | var targetFaces = brushModelInfo["faceArr"] 1513 | var targetNodeArr = [] 1514 | var pathArr = [] 1515 | 1516 | 1517 | #if dict.has("SPAWNFLAGS"): 1518 | # if int(dict["SPAWNFLAGS"]) == 8: 1519 | # deleteModelNode(brushModelInfo) 1520 | 1521 | if !dict.has("TARGET"):#if train dosen't have a traget corner it won't move so nothing needs to happen 1522 | return 1523 | 1524 | var a = dict["TARGET"] 1525 | print("Start loop") 1526 | while(a != null): 1527 | 1528 | if !cornerPaths.has(a): 1529 | return 1530 | 1531 | var b = cornerPaths[a] 1532 | 1533 | 1534 | pathArr.append(a) 1535 | a = b 1536 | #print(pathArr.size()) 1537 | if cornerPaths.size()>1: 1538 | if b == pathArr[0]:#the loop has been closed 1539 | break 1540 | 1541 | 1542 | 1543 | for i in targetFaces: 1544 | if faceMeshNodes.has(i): 1545 | targetNodeArr.append(faceMeshNodes[i].get_parent().name) 1546 | 1547 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/func_train.gd") 1548 | var trainNode= Spatial.new() 1549 | 1550 | trainNode.set_meta("targetNodePaths",targetNodeArr) 1551 | trainNode.set_meta("path",pathArr) 1552 | trainNode.set_script(scriptRes) 1553 | 1554 | get_parent().add_child(trainNode) 1555 | 1556 | 1557 | 1558 | func parseTrackTrain(dict): 1559 | var pathArr = [] 1560 | var faceMeshNodes = get_parent().faceMeshNodes 1561 | var bushModelInfo = getModelInfoFromDict(dict) 1562 | var targetFaces = bushModelInfo["faceArr"] 1563 | var targetNodeArr = [] 1564 | var origin = Vector3.ZERO 1565 | var sound = -1 1566 | origin = textToVector3(dict["ORIGIN"]) 1567 | 1568 | 1569 | for i in targetFaces: 1570 | if faceMeshNodes.has(i): 1571 | setOrigin(faceMeshNodes[i].get_parent(),origin) 1572 | 1573 | targetNodeArr.append(faceMeshNodes[i].get_parent().name) 1574 | 1575 | if !dict.has("TARGET"):#if train dosen't have a traget corner it won't move so nothing needs to happen 1576 | return 1577 | 1578 | var a = dict["TARGET"] 1579 | 1580 | if !trackPaths.has(a): 1581 | print("track not found for train:",a) 1582 | return 1583 | 1584 | while(a != null): 1585 | var b = trackPaths[a] 1586 | 1587 | pathArr.append(a) 1588 | a = b 1589 | 1590 | if !trackPaths.has(a): 1591 | print("couldn't find:", a) 1592 | break 1593 | 1594 | if trackPaths.size()>1: 1595 | if b == pathArr[0]:#the loop has been closed 1596 | pathArr.append(b) 1597 | break 1598 | 1599 | var path = Path.new() 1600 | var tarr = [] 1601 | for i in pathArr: 1602 | var node : Position3D = (get_parent().find_node(i,true,false)) 1603 | if node.has_meta("trigger"): 1604 | var triggerName = node.get_meta("trigger") 1605 | 1606 | path.set_meta(triggerName,node.translation) 1607 | 1608 | 1609 | 1610 | path.curve.add_point(node.translation) 1611 | 1612 | 1613 | 1614 | 1615 | 1616 | path.add_child(PathFollow.new()) 1617 | get_parent().add_child(path) 1618 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/func_track_train.gd") 1619 | var trainNode= Spatial.new() 1620 | 1621 | if dict.has("SOUNDS"): 1622 | sound = int(dict["SOUNDS"]) 1623 | var audioNode = get_parent().createAudioPlayer3DfromName(TRAINSOUNDS[sound]) 1624 | audioNode.name = "moveSound" 1625 | trainNode.add_child(audioNode) 1626 | 1627 | trainNode.set_meta("scaleFactor",scaleFactor) 1628 | trainNode.translation = origin 1629 | trainNode.name ="func_tracktrain" 1630 | trainNode.set_meta("targetNodePaths",targetNodeArr) 1631 | trainNode.set_meta("path",pathArr) 1632 | trainNode.set_meta("pathName",path.name) 1633 | trainNode.set_script(scriptRes) 1634 | 1635 | get_parent().add_child(trainNode) 1636 | 1637 | func parseAmbientGeneric(dict): 1638 | if !dict.has("MESSAGE"): 1639 | return 1640 | var par = get_parent().get_node_or_null("Ambient Sounds") 1641 | if par == null: 1642 | par = Spatial.new() 1643 | par.name = "Ambient Sounds" 1644 | get_parent().add_child(par) 1645 | 1646 | 1647 | 1648 | 1649 | var pos = textToVector3(dict["ORIGIN"]) 1650 | var audioNode = get_parent().createAudioPlayer3DfromName(dict["MESSAGE"].to_lower()) 1651 | if dict.has("MESSAGE"): 1652 | audioNode.name= dict["MESSAGE"] 1653 | var volume = int(dict["HEALTH"]) 1654 | #audioNode.unit_db = 0.5 * (volume/10.0) 1655 | audioNode.max_db = 1 1656 | if dict.has("TARGETNAME"): 1657 | audioNode.add_to_group(dict["TARGETNAME"],true) 1658 | 1659 | audioNode.translation = pos 1660 | audioNode.unit_size = 7 * (volume/10.0) 1661 | 1662 | 1663 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/ambient_generic.gd") 1664 | audioNode.set_script(scriptRes) 1665 | audioNode.autoplay = true 1666 | var playEverywhere = false 1667 | if dict.has("SPAWNFLAGS"): 1668 | var flags = int(dict["SPAWNFLAGS"]) 1669 | 1670 | if flags & (1 << 0) > 0: 1671 | audioNode.unit_size = 100000000 1672 | playEverywhere = true 1673 | 1674 | if flags & (1 << 1) > 0: 1675 | pass 1676 | #print("small radius") 1677 | 1678 | if(flags & (1 << 2 )) > 0: 1679 | pass 1680 | #print("medium radius") 1681 | 1682 | if(flags & (1 << 3)) > 0: 1683 | pass 1684 | #print("large radius") 1685 | 1686 | if(flags & (1 << 4)) > 0: 1687 | audioNode.autoplay = false 1688 | 1689 | if(flags & (1 << 5)) > 0: 1690 | pass 1691 | #print("not toggled") 1692 | 1693 | if dict.has("TARGETNAME"): 1694 | audioNode.add_to_group(dict["TARGETNAME"],true) 1695 | 1696 | par.add_child(audioNode) 1697 | 1698 | #audioNode.stream.save_to_wav("test.wav") 1699 | 1700 | func parseModel(dict,modelName): 1701 | return 1702 | var pos = textToVector3(dict["ORIGIN"]) 1703 | var baseDir = get_parent().wadDict["baseDirectory"] 1704 | var mesh = $"../mdlLoader".mdlParse(baseDir + "models/" + modelName) 1705 | mesh.name = modelName.split(".")[0] 1706 | 1707 | 1708 | mesh.scale *= scaleFactor 1709 | #mesh.rotation_degrees.x -= 90 1710 | mesh.translation = pos 1711 | 1712 | 1713 | get_parent().add_child(mesh) 1714 | 1715 | if dict.has("TARGETNAME"): 1716 | mesh.add_to_group(dict["TARGETNAME"],true) 1717 | 1718 | #breakpoint 1719 | 1720 | 1721 | func parseIllusionary(dict): 1722 | var modelInfo = getModelInfoFromDict(dict) 1723 | deleteModelCollision(modelInfo) 1724 | 1725 | func deleteModelNode(modelInfo): 1726 | var modelFaceIdxs = modelInfo["faceArr"] 1727 | var deleted = false 1728 | for faceIdx in modelFaceIdxs: 1729 | if get_parent().faceMeshNodes.has(faceIdx): 1730 | if get_parent().faceMeshNodes[faceIdx] != null:#whis is this nulled? 1731 | get_parent().faceMeshNodes[faceIdx].get_parent().queue_free() 1732 | deleted = true 1733 | 1734 | #if get_parent().faceMeshNodes[faceIdx] == null: 1735 | # breakpoint 1736 | 1737 | 1738 | func deleteModelCollision(modelInfo): 1739 | var modelFaceIdxs = modelInfo["faceArr"] 1740 | var deleted = false 1741 | for faceIdx in modelFaceIdxs: 1742 | if get_parent().faceMeshNodes.has(faceIdx): 1743 | if get_parent().faceMeshNodes[faceIdx] != null:#why is this nulled? 1744 | 1745 | 1746 | #static body 1747 | #-collision shape 1748 | #-mesh instance 1749 | 1750 | #some iteams like func_illusionary will just be a mesh instance so we skip them 1751 | 1752 | var par = get_parent().faceMeshNodes[faceIdx].get_parent()#the static body node 1753 | if par.get_class() != "StaticBody": 1754 | continue 1755 | for i in par.get_children(): 1756 | if i.get_class() == "MeshInstance": 1757 | par.remove_child(i) 1758 | i.translation += par.translation 1759 | var parp = i.get_parent() 1760 | par.get_parent().add_child(i) 1761 | else: 1762 | i.queue_free() 1763 | 1764 | par.queue_free() 1765 | deleted = true 1766 | 1767 | func guessWadPath(path): 1768 | if path.find_last("Half-Life") != -1: 1769 | var pathPre = path.substr(0, path.find_last("Half-Life")) 1770 | return pathPre + "Half-Life/valve/halflife.wad" 1771 | else: 1772 | return null 1773 | 1774 | func loadMP3asAudioPlayer(path): 1775 | var file = File.new() 1776 | file.open(path,File.READ) 1777 | var data = file.get_buffer(file.get_len()) 1778 | file.close() 1779 | var mp3 = AudioStreamMP3.new() 1780 | var player = AudioStreamPlayer.new() 1781 | 1782 | mp3.data = data 1783 | player.stream = mp3 1784 | return player 1785 | 1786 | 1787 | func createInteractionBoxAndDeleteBrushModel(dict,parentName, nodename = ""): 1788 | var modelInfo = getModelInfoFromDict(dict) 1789 | var interactionBox = createInteractionAreaNode(modelInfo) 1790 | 1791 | interactionBox.translation = modelInfo["BBMin"]+ (modelInfo["BBMax"] - modelInfo["BBMin"])*0.5 1792 | if nodename != "": 1793 | interactionBox.name = nodename 1794 | 1795 | get_parent().get_node(parentName).add_child(interactionBox) 1796 | deleteModelNode(modelInfo) 1797 | 1798 | 1799 | func parseNpc(dict): 1800 | return 1801 | var pos = textToVector3(dict["ORIGIN"]) 1802 | var baseDir = get_parent().wadDict["baseDirectory"] 1803 | var mesh = $"../mdlLoader".mdlParse(baseDir + "models/gman.mdl") 1804 | 1805 | mesh.scale *= scaleFactor 1806 | mesh.translation = pos 1807 | 1808 | get_parent().add_child(mesh) 1809 | 1810 | 1811 | func nullFunction(dict): 1812 | return 1813 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/src/imageBuilder.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Node 3 | 4 | func _ready(): 5 | set_meta("hidden",true) 6 | 7 | func createImage(fileDict,isDecal = false,imageDictParam = null):#imageDictParam is used when the texture is within the BSP itself instead of external WAD 8 | var imageDict 9 | if imageDictParam == null: 10 | imageDict = parseTexture(fileDict["file"],fileDict["offset"],fileDict["size"]) 11 | else: 12 | imageDict = imageDictParam 13 | 14 | if !imageDict.has("data"): 15 | return 16 | 17 | var data = imageDict["data"] 18 | 19 | var pallete = imageDict["palette"] 20 | #var isDecal = imageDict["name"][0] == "{" and isDecal 21 | var w = imageDict["dim"][0] 22 | var h = imageDict["dim"][1] 23 | var image : Image = Image.new() 24 | image.create(w,h,false,Image.FORMAT_RGBA8) 25 | image.lock() 26 | 27 | 28 | for y in h: 29 | for x in w: 30 | var colorIndex = data[x+(y*w)] 31 | if isDecal == false: 32 | var color = pallete[colorIndex] 33 | image.set_pixel(x,y,color) 34 | else: 35 | var color = pallete[colorIndex] 36 | var baseColor = pallete[pallete.size()-1] 37 | image.set_pixel(x,y,Color(baseColor.r,baseColor.g,baseColor.b,1-color.r)) 38 | 39 | # var RGBA : PoolByteArray = [] 40 | #RGBA.resize(w*h*4) 41 | #var count = 0 42 | 43 | #for y in h: 44 | # for x in w: 45 | # var colorIndex = data[x+(y*w)] 46 | # if isDecal == false: 47 | # var color = pallete[colorIndex] 48 | # RGBA[count] = color.r*255 49 | # RGBA[count+1] = color.g*255 50 | # RGBA[count+2] = color.b*255 51 | # RGBA[count+3] = color.a*255 52 | # count += 4 53 | 54 | #image.create_from_data(w,h,false,image.FORMAT_RGBA8,RGBA) 55 | 56 | image.unlock() 57 | var texture = ImageTexture.new() 58 | 59 | 60 | 61 | texture.create_from_image(image) 62 | if !get_parent().textureFiltering: 63 | texture.flags -= texture.FLAG_FILTER 64 | return texture 65 | 66 | func parseTexture(file,offset,size): 67 | var textureDict = {} 68 | 69 | file.seek(offset) 70 | 71 | textureDict["name"] = file.get_String(16) 72 | 73 | var w = file.get_32() 74 | var h = file.get_32() 75 | var mip1 = file.get_32u() 76 | var mip2 = file.get_32u() 77 | var mip3 = file.get_32u() 78 | var mip4 = file.get_32u() 79 | 80 | var mip1sz = mip2 - mip1 81 | var mip4sz = mip1sz / 64 82 | 83 | file.seek(mip1+offset) 84 | 85 | var data = [] 86 | var pallete = [] 87 | 88 | for p in (w*h): 89 | data.append(file.get_8()) 90 | 91 | file.seek(mip4+offset+mip4sz+2) 92 | 93 | for c in 256: 94 | var r = file.get_8() / 255.0 95 | var g = file.get_8() / 255.0 96 | var b = file.get_8() / 255.0 97 | if r== 0 and g == 0 and b== 1: 98 | pallete.append(Color(0,0,0,0)) 99 | else: 100 | pallete.append(Color(r,g,b)) 101 | 102 | textureDict["dim"] = [w,h] 103 | textureDict["data"] = data 104 | textureDict["palette"] = pallete 105 | 106 | #get_parent().imageBuilder.createImage(textureDict) 107 | return textureDict 108 | 109 | func createImageFromName(txtureName): 110 | for t in get_parent().textures: 111 | if t.name == txtureName: 112 | breakpoint 113 | 114 | func createImageArrFromSpr(path): 115 | 116 | var file = load("res://addons/gldsrcBSP/DFile.gd").new() 117 | file.loadFile(path) 118 | var magic = file.get_String(4) 119 | var version = file.get_32() 120 | var spriteType = file.get_32() 121 | var textureFormat = file.get_32() 122 | var boundingRdadious = file.get_float32() 123 | var maxW = file.get_32() 124 | var maxH = file.get_32() 125 | var numFrames = file.get_32() 126 | var beamLen = file.get_float32() 127 | var syncType = file.get_32() 128 | 129 | var sizeOfPalette = file.get_16() 130 | var pallete = [] 131 | for c in sizeOfPalette: 132 | var r = file.get_8() / 255.0 133 | var g = file.get_8() / 255.0 134 | var b = file.get_8() / 255.0 135 | pallete.append(Color(r,g,b,1)) 136 | 137 | var retImages = [] 138 | 139 | for i in numFrames: 140 | var frameGroup = file.get_32() 141 | var frameOriginX = file.get_32() 142 | var frameOriginY = file.get_32() 143 | var frameW = file.get_32() 144 | var frameH = file.get_32() 145 | 146 | var w = frameW 147 | var h = frameH 148 | var image : Image = Image.new() 149 | image.create(w,h,false,Image.FORMAT_RGBA8) 150 | image.lock() 151 | var lan = file.get_len() 152 | var data = file.get_buffer(w*h) 153 | 154 | for y in h: 155 | for x in w: 156 | var colorIndex = data[x+(y*w)] 157 | var color = pallete[colorIndex] 158 | image.set_pixel(x,y,color) 159 | 160 | retImages.append(image) 161 | 162 | return retImages 163 | 164 | func createTextureFromSpr(path): 165 | 166 | 167 | var imgArr = createImageArrFromSpr(path) 168 | var texture = AnimatedTexture.new() 169 | texture.frames = imgArr.size() 170 | 171 | for i in imgArr.size(): 172 | var frame = ImageTexture.new() 173 | frame.create_from_image(imgArr[i]) 174 | texture.set_frame_texture(i,frame) 175 | 176 | 177 | return texture 178 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/src/levelBuilder.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Spatial 3 | 4 | #var faces = [] 5 | var edges 6 | var surfEdges 7 | var vertices 8 | var planes 9 | var textures 10 | var textureInfos 11 | var brushModels 12 | var geometryParentNode = null 13 | var edgeToFaceIndexMap 14 | var renderables 15 | var renderableEdges 16 | #var workingFaceMeshNodes = {} 17 | var linkedFacesDict = {} 18 | var theFaceIndex = 0 19 | var hotFaces 20 | var renderModeFaces 21 | var skyMat = null 22 | var lightmapOffset = null 23 | var cubeMapShader = preload("res://addons/gldsrcBSP/cubemap.shader") 24 | var skyCubemap = null 25 | var atlasTexture : ImageTexture 26 | var atlasDim 27 | var kinematicBodies = false 28 | var rads = { 29 | "+0~GENERIC65": Color(1,1,1), 30 | "+0~GENERIC85":Color(1,1,1), 31 | "+0~GENERIC86":Color(1,1,1), 32 | "+0~GENERIC86B":Color(1,1,1), 33 | "+0~GENERIC86R":Color(1,1,1), 34 | "GENERIC87A":Color(1,1,1), 35 | "GENERIC88A":Color(1,1,1), 36 | "GENERIC89A":Color(1,1,1), 37 | "GENERIC90A":Color(1,1,1), 38 | "GENERIC105":Color(1,1,1), 39 | "GENERIC106":Color(1,1,1), 40 | "GENERIC107":Color(1,1,1), 41 | "GEN_VEND1":Color(1,1,1), 42 | "EMERGLIGHT":Color(1,1,1), 43 | "~+0LAB1_W6D" : Color(1,1,1), 44 | "~+0LAB1_W6" : Color(1,1,1), 45 | "~+0LAB1_W7":Color(1,1,1), 46 | "SKKYLITE":Color(1,1,1), 47 | "~LIGHT2A" : Color(1,1,1), 48 | "~LIGHT3B" : Color(1,1,1), 49 | "~LIGHT3C" : Color(1,1,1), 50 | "~LIGHT5A" : Color(1,1,1), 51 | "~LIGHT5F" : Color(1,1,1), 52 | "+0~TNNL_LGT1" : Color(1,1,1), 53 | "+0~TNNL_LGT2" : Color(1,1,1), 54 | "+0~TNNL_LGT3" : Color(1,1,1), 55 | "+0~TNNL_LGT4" : Color(1,1,1), 56 | "~EMERGLIGHT":Color(1,1,1), 57 | "+0~FIFTS_LGHT01": Color(1,1,1), 58 | "+0~FIFTIES_LGT2": Color(1,1,1), 59 | "+0~FIFTS_LGHT4": Color(1,1,1), 60 | "+0~DRKMTLS1" : Color(1,1,1), 61 | "0~DRKMTLGT1" : Color(1,1,1), 62 | "+0~DRKMTLS2" : Color(1,1,1), 63 | "+0~DRKMTLS2C" : Color(1,1,1), 64 | "+0DRKMTL_SCRN" : Color(1,1,1), 65 | "+0~LAB_CRT8":Color(1,1,1), 66 | "RED":Color(1,0,0), 67 | "YELLOW":Color(1,1,0), 68 | "~SPOTYELLOW":Color(1,1,1), 69 | "+0~LIGHT2A":Color(1,1,1), 70 | "+A~FIFTS_LGHT4":Color(1,1,1) 71 | 72 | } 73 | 74 | 75 | 76 | func _ready(): 77 | set_meta("hidden",true) 78 | 79 | #mat.set_shader_param("cube_map",skyCubemap) 80 | 81 | func createLevel(dict,wadDict): 82 | 83 | renderModeFaces = get_parent().renderModeFaces 84 | geometryParentNode = Spatial.new() 85 | geometryParentNode.name = "Geometry" 86 | get_parent().add_child(geometryParentNode) 87 | vertices = get_parent().vertices 88 | #faces = get_parent().faces 89 | surfEdges = get_parent().surfaces 90 | edges = get_parent().edges 91 | planes = get_parent().planes 92 | textureInfos = get_parent().textureInfo 93 | textures = get_parent().textures 94 | brushModels = get_parent().brushModels 95 | hotFaces = get_parent().hotFaces 96 | edgeToFaceIndexMap = get_parent().edgeToFaceIndexMap 97 | lightmapOffset = get_parent().ligthMapOffset 98 | #atlasTexture = get_parent().get_node("lightmapAtlas").getTexture() 99 | var a = OS.get_system_time_msecs() 100 | var atlasDict = get_parent().get_node("lightmapAtlas").initAtlas() 101 | atlasDim = get_parent().get_node("lightmapAtlas").getSize() 102 | atlasTexture = atlasDict["texture"] 103 | var atlasRects = atlasDict["rects"] 104 | 105 | if get_parent().optimize == true: 106 | #a = OS.get_system_time_msecs() 107 | generateEdgeTrackerFaces() 108 | #combineEdgeTracker() 109 | #print("Generate edge tracker faces:", OS.get_system_time_msecs()-a) 110 | mergeBrushModelFaces3() 111 | 112 | #a = OS.get_system_time_msecs() 113 | var renderables= get_parent().renderables 114 | 115 | for faceIdx in renderables.size(): 116 | var face = renderables[faceIdx] 117 | if face.empty(): 118 | continue 119 | var faceIndex = faceIdx#faces.find(face) 120 | var meshNode = null 121 | 122 | 123 | var fanMesh = createMeshFromFanArr(face,faceIndex) 124 | 125 | if fanMesh != null: 126 | fanMesh.use_in_baked_light = true 127 | get_parent().faceMeshNodes[faceIndex] = fanMesh 128 | geometryParentNode.add_child(fanMesh) 129 | 130 | 131 | #get_parent().get_node("lightmapAtlas").saveToFile() 132 | 133 | a = OS.get_system_time_msecs() 134 | if get_parent().collisions == true: 135 | if get_parent().faceMeshNodes!= null: 136 | for f in get_parent().faceMeshNodes.values(): 137 | if f != null: 138 | createCollisionsForMesh(f) 139 | else: 140 | for f in get_parent().faceMeshNodes.values(): 141 | var newParent = Spatial.new() 142 | newParent.add_child(f) 143 | geometryParentNode.add_child(newParent) 144 | 145 | #print("collisions:",OS.get_system_time_msecs()-a) 146 | if get_parent().textureLights: 147 | textureLights() 148 | 149 | 150 | 151 | func getCenter(vertices): 152 | var sum = Vector3.ZERO 153 | for i in vertices: 154 | sum += i 155 | 156 | return sum/vertices.size() 157 | 158 | func getCenterFanArr(fans): 159 | var center= Vector3.ZERO 160 | var count = 0 161 | for textureName in fans: 162 | for i in fans[textureName]: 163 | center += getCenter(i["verts"]) 164 | count += 1 165 | # center += getCenter(fan["verts"]) 166 | 167 | # count +=1 168 | 169 | 170 | return center/count 171 | 172 | func getCenter2d(vertices): 173 | var sum = Vector2.ZERO 174 | for i in vertices: 175 | sum += i 176 | 177 | return sum/vertices.size() 178 | 179 | func fanMerge(fans): 180 | for textureName in fans: 181 | for fan in fans[textureName]: 182 | if fan != null: 183 | mergeAfan(fans,fan) 184 | 185 | 186 | func mergeAfan(fans,fan1): 187 | for textureName in fans: 188 | for fan2 in fans[textureName]: 189 | #fan2 = fan2[textureName] 190 | if fan1["verts"] == null: continue 191 | if fan2["verts"] == null: continue 192 | 193 | if fan1 == fan2: 194 | continue 195 | if fan1["normal"] == fan2["normal"]: 196 | var comb = combineVerts(fan1["verts"],fan2["verts"]) 197 | if comb != null: 198 | fan1["verts"] = comb 199 | fan2["verts"] = [] 200 | 201 | 202 | 203 | func getMatType(textureName): 204 | var lookupString = textureName 205 | if lookupString.length() > 12: 206 | lookupString = lookupString.substr(0,12) 207 | 208 | lookupString = lookupString.trim_prefix("!") 209 | lookupString = lookupString.trim_prefix("~") 210 | lookupString = lookupString.trim_prefix("{") 211 | 212 | 213 | var matType = "C" 214 | if get_parent().textureToMaterialDict.has(lookupString): 215 | matType = get_parent().textureToMaterialDict[lookupString] 216 | 217 | return matType 218 | 219 | #var surf : SurfaceTool = SurfaceTool.new() 220 | 221 | func createMeshFromFanArr(fans,faceIndex): 222 | var center = getCenterFanArr(fans) 223 | var texture 224 | 225 | var surf: SurfaceTool = SurfaceTool.new() 226 | var runningMesh = ArrayMesh.new() 227 | 228 | var mat# : SpatialMaterial 229 | surf.begin(Mesh.PRIMITIVE_TRIANGLES) 230 | var count = 0 231 | 232 | var atlasPosArr = get_parent().get_node("lightmapAtlas").atlasPos 233 | var atlasDimArr = get_parent().get_node("lightmapAtlas").atlasImgDimArr 234 | var matType = null #currently I'm only picking a mat at random this can fail for multi-material meshes 235 | for textureName in fans: 236 | var localSurf = SurfaceTool.new() 237 | if matType == null: 238 | matType = getMatType(textureName) 239 | texture = get_parent().fetchTexture(textureName) 240 | 241 | localSurf.set_material(mat) 242 | localSurf.begin(Mesh.PRIMITIVE_TRIANGLES) 243 | 244 | var localLightmap 245 | 246 | for locFan in fans[textureName]: 247 | var fIdx = locFan["faceIndex"] 248 | var triVerts = locFan["verts"] 249 | var triNormals = [] 250 | var triUV = locFan["uv"] 251 | var vertsLocal = [] 252 | localLightmap =locFan["localLightmap"] 253 | 254 | for i in triVerts: 255 | vertsLocal.append(i-center) 256 | triNormals.append(locFan["normal"]) 257 | 258 | var lightmapUV = locFan["lightmapUV"] 259 | 260 | for i in triUV.size(): 261 | triUV[i] /= texture.get_size() 262 | # 263 | 264 | var atlasPos = atlasPosArr[fIdx] 265 | var dimInAtlas = atlasDimArr[fIdx] 266 | 267 | var mins = Vector2(INF,INF) 268 | var maxs = Vector2(-INF,-INF) 269 | var locDim = localLightmap.get_size() 270 | 271 | for i in lightmapUV.size(): 272 | if lightmapUV[i].x < mins.x : mins.x = lightmapUV[i].x 273 | if lightmapUV[i].x < mins.y : mins.y = lightmapUV[i].y 274 | 275 | if lightmapUV[i].x > maxs.x : maxs.x = lightmapUV[i].x 276 | if lightmapUV[i].y > maxs.y : maxs.y = lightmapUV[i].y 277 | #print(String(fIdx),":",lightmapUV) 278 | 279 | mins+=Vector2(1,1)/locDim 280 | maxs-=Vector2(1,1)/locDim 281 | 282 | for i in lightmapUV.size(): 283 | lightmapUV[i].x = lerp(mins.x,maxs.x,lightmapUV[i].x) 284 | lightmapUV[i].y = lerp(mins.y,maxs.y,lightmapUV[i].y) 285 | 286 | lightmapUV[i]*=localLightmap.get_size() #convert to pixel 287 | lightmapUV[i] += atlasPosArr[fIdx]#shift over the position in the atlas 288 | lightmapUV[i] /= atlasDim#convert to 289 | #lightmapUV[i] /= get_parent().scale_factor) 290 | 291 | if !get_parent().disableTextures: 292 | if textureName!="SKY": 293 | mat = createMat(texture,textureName,renderModeFaces) 294 | else: 295 | mat = createMatSky() 296 | 297 | localSurf.add_triangle_fan(vertsLocal,triUV,[],lightmapUV,triNormals) 298 | 299 | localSurf.commit(runningMesh) 300 | 301 | 302 | if mat!=null: 303 | if textureName!="SKY": 304 | mat.albedo_texture = texture 305 | if get_parent().importLightmaps: 306 | mat.detail_uv_layer = SpatialMaterial.DETAIL_UV_2 307 | mat.detail_enabled = true 308 | mat.detail_albedo = atlasTexture 309 | mat.detail_blend_mode = SpatialMaterial.BLEND_MODE_MUL 310 | 311 | runningMesh.surface_set_material(count,mat) 312 | runningMesh.surface_set_name(count,textureName) 313 | count+=1 314 | 315 | 316 | surf.commit(runningMesh) 317 | 318 | var meshNode = MeshInstance.new() 319 | meshNode.name = "face_mesh_" + String(faceIndex) 320 | meshNode.mesh = runningMesh 321 | 322 | # Fix real-time light shadows by ensuring that even "hollow" faces cast shadows. 323 | # This is enabled even when lightmap generation is used, as lightmaps and real-time lights can coexist. 324 | meshNode.cast_shadow = MeshInstance.SHADOW_CASTING_SETTING_DOUBLE_SIDED 325 | 326 | # Allow baking global illumination with GIProbe. 327 | # BakedLightmap can't be used correctly since there is no UV2 generated. 328 | meshNode.use_in_baked_light = true 329 | 330 | get_parent().faceMeshNodes[faceIndex] = meshNode 331 | 332 | meshNode.translation = center 333 | 334 | meshNode.set_meta("textureName",fans.keys()[0]) 335 | meshNode.set_meta("fans",fans) 336 | meshNode.set_meta("materialType",matType) 337 | if hotFaces.has(faceIndex): 338 | meshNode.set_meta("hotFace",true) 339 | return meshNode 340 | 341 | 342 | func createMat(texture,textureName,render = null): 343 | 344 | 345 | var matCacheName = textureName# + String(texInfo["fSShift"]) + String(texInfo["fTShift"])# + String(texInfo["vS"]) + String(texInfo["vT"]) 346 | 347 | var matDict = get_parent().fetchMaterial(matCacheName) 348 | var mat : SpatialMaterial = matDict["material"] 349 | 350 | 351 | 352 | if matDict["isFirstInstance"]: 353 | if texture != null: 354 | var textureDim = texture.get_size() 355 | mat.albedo_texture = texture 356 | 357 | if texture.get_data().detect_alpha() != 0: 358 | mat.flags_transparent =true 359 | #if rads.has(textureName): 360 | 361 | mat.flags_world_triplanar = true 362 | mat.emission_enabled = true 363 | #mat.emission_texture = 364 | #mat.uv1_triplanar = true 365 | get_parent().saveToMaterialCache(matCacheName,mat) 366 | 367 | return(mat) 368 | 369 | func createMatSky(): 370 | 371 | if skyMat == null: 372 | var path = get_parent().skyTexture 373 | var bmpLoader = get_parent().get_node("bmpLoader") 374 | 375 | 376 | var left = loadTGAasImage(path + "lf.tga") 377 | var right = loadTGAasImage(path + "rt.tga") 378 | var bottom = loadTGAasImage(path + "dn.tga") 379 | var top = loadTGAasImage(path + "up.tga") 380 | var front = loadTGAasImage(path + "ft.tga") 381 | var back = loadTGAasImage(path + "bk.tga") 382 | 383 | top = rotImage(top,"top") 384 | bottom = rotImage(bottom,"bottom") 385 | #var rect = Rect2(Vector2(-256,-256),Vector2(256,256)) 386 | #top.blit_rect(top,rect,Vector2(256,256)) 387 | skyCubemap = CubeMap.new() 388 | if get_parent().textureFilterSkyBox == false: 389 | skyCubemap.flags -= skyCubemap.FLAG_FILTER 390 | skyCubemap.set_side(0,left) 391 | skyCubemap.set_side(1,right) 392 | skyCubemap.set_side(2,bottom) 393 | skyCubemap.set_side(3,top) 394 | skyCubemap.set_side(4,front) 395 | skyCubemap.set_side(5,back) 396 | 397 | 398 | var mat = ShaderMaterial.new() 399 | mat.set_shader_param("cube_map",skyCubemap) 400 | mat.shader = cubeMapShader 401 | skyMat = mat 402 | 403 | return skyMat 404 | 405 | return(skyMat) 406 | 407 | 408 | 409 | 410 | func createCollisionsForMesh(meshNode): 411 | 412 | #if meshNode.get_meta("textureName")[0] == "!": 413 | # return 414 | 415 | var center = meshNode.translation 416 | meshNode.translation = Vector3.ZERO 417 | if meshNode.get_meta("textureName")[0] != "!":# and meshNode.has_meta("hotFace"): 418 | meshNode.create_trimesh_collision() 419 | else: 420 | meshNode.scale = Vector3(0.99,0.99,0.99) 421 | meshNode.create_convex_collision() 422 | 423 | 424 | meshNode.get_parent().remove_child(meshNode) 425 | var staticBodyNode = meshNode.get_child(0) 426 | 427 | if meshNode.has_meta("hotFace") and kinematicBodies: 428 | var shape = staticBodyNode.get_child(0) 429 | shape.get_parent().remove_child(shape) 430 | staticBodyNode.queue_free() 431 | staticBodyNode = KinematicBody.new() 432 | staticBodyNode.add_child(shape) 433 | 434 | if meshNode.get_meta("textureName")[0] == "!": 435 | var shape = staticBodyNode.get_child(0) 436 | shape.get_parent().remove_child(shape) 437 | staticBodyNode.queue_free() 438 | staticBodyNode = Area.new() 439 | staticBodyNode.add_child(shape) 440 | 441 | meshNode.remove_child(staticBodyNode) 442 | meshNode.name = "face" + String(theFaceIndex) 443 | staticBodyNode.translation = center 444 | 445 | if meshNode.get_meta("textureName")[0] == "!": 446 | var scriptRes = load("res://addons/gldsrcBSP/funcScripts/water.gd") 447 | staticBodyNode.set_script(scriptRes) 448 | staticBodyNode.add_child(meshNode) 449 | if meshNode.has_meta("materialType"): 450 | staticBodyNode.set_meta("materialType", meshNode.get_meta("materialType")) 451 | 452 | 453 | 454 | geometryParentNode.add_child(staticBodyNode) 455 | return 456 | 457 | func getBB(verts): 458 | var minX = INF 459 | var minY = INF 460 | var minZ = INF 461 | 462 | var maxX = -INF 463 | var maxY = -INF 464 | var maxZ = -INF 465 | 466 | for v in verts: 467 | if v.x < minX: 468 | minX = v.x 469 | if v.y < minY: 470 | minY = v.y 471 | if v.z < minZ: 472 | minZ = v.z 473 | 474 | if v.x > maxX: 475 | maxX = v.x 476 | if v.y > maxY: 477 | maxY = v.y 478 | if v.z > maxZ: 479 | maxZ = v.z 480 | 481 | 482 | var minDim = Vector3(minX,minY,minZ) 483 | var maxDim = Vector3(maxX,maxY,maxZ) 484 | var absDim = maxDim - minDim 485 | return({"dim":absDim,"min":minDim,"max":maxDim}) 486 | 487 | func projectToXYbasic(verts): 488 | var out = [] 489 | var origin = getCenter(verts) 490 | var planeLine1 = (verts[1] - origin).normalized() 491 | var planeLine2 = (verts[2] - origin).normalized() 492 | 493 | 494 | 495 | var X = planeLine1 496 | var Z = planeLine1.cross(planeLine2).normalized() 497 | var Y = Z.cross(X).normalized() 498 | 499 | var t = Transform(X,Y,Z,Vector3.ZERO) 500 | 501 | for vert in verts: 502 | out.append(t.xform_inv(vert)) 503 | 504 | return {"vertices":out,"transform":t,"origin":origin} 505 | 506 | 507 | 508 | func saveVertsAsPolyImage(verts,namStr): 509 | #print(verts) 510 | var poly = Polygon2D.new() 511 | poly.scale *= 10 512 | poly.polygon = verts 513 | var packed_scene = PackedScene.new() 514 | packed_scene.pack(poly) 515 | ResourceSaver.save("res://" + namStr + ".tscn",packed_scene) 516 | 517 | func removeADup(v): 518 | #print(v.size()) 519 | if v.size() == 1: 520 | return 521 | var indexes = [] 522 | for j in v.size(): 523 | for k in range(j+1,v.size()): 524 | 525 | var a = v[j] 526 | var b = v[k] 527 | var diff = a-b 528 | 529 | if(abs(diff.x) < 0.0001 and abs(diff.y) < 0.0001 and abs(diff.z) < 0.0001): 530 | v.remove(k) 531 | return true 532 | 533 | return false 534 | 535 | func findCommonverts(v1,v2): 536 | var commonIndexes = [] 537 | var count = 0 538 | #if v1.size() TL.y: TL.y = v.y 661 | if v.z < TL.z: TL.z = v.z 662 | return Vector3(TL.x,TL.y,TL.z) 663 | 664 | func getBottomRightVert(verts): 665 | var TL = Vector3(-INF,INF,-INF) 666 | for v in verts: 667 | if v.x > TL.x: TL.x = v.x 668 | if v.y < TL.y: TL.y = v.y 669 | if v.z > TL.z: TL.z = v.z 670 | return Vector3(TL.x,TL.y,TL.z) 671 | 672 | 673 | var out = [] 674 | 675 | for v in verts: 676 | out.append(transform.xform_inv(v)) 677 | 678 | var tl = getTopLeftVert(out) 679 | for v in out.size(): 680 | out[v] -= tl 681 | 682 | return out 683 | 684 | 685 | func uvProjection(vert,normal): 686 | var e1 = normal.cross(Vector3(0,1,0)).normalized() 687 | if e1 == Vector3.ZERO: #is parallel to x axis 688 | e1 = normal.cross(Vector3(0,0,1)).normalized() 689 | 690 | var e2 = normal.cross(e1).normalized() 691 | var u = vert.dot(e1) 692 | var v = vert.dot(e2) 693 | return Vector2(u,v) 694 | 695 | 696 | 697 | func removeColinear(verts): 698 | var out = [] 699 | 700 | for v in verts.size(): 701 | var a = verts[(v-1)%verts.size()] 702 | var b = verts[(v)] 703 | var c = verts[(v+1)%verts.size()] 704 | if (b-a).normalized() == (c-b).normalized(): 705 | continue 706 | 707 | out.append(verts[v]) 708 | return out 709 | 710 | 711 | 712 | func generateEdgeTrackerFaces(): 713 | var retMeshes = [] 714 | var hotFaces = get_parent().hotFaces 715 | var firstskipped = false 716 | 717 | var mergeTextureFactor = get_parent() 718 | renderables = get_parent().renderables 719 | renderableEdges = get_parent().renderableEdges 720 | var faceIdx = -1 721 | for face in renderables: 722 | faceIdx += 1 723 | if face.size()==0: 724 | continue 725 | 726 | 727 | var mergeHappened = true 728 | while(mergeHappened): 729 | mergeHappened = false 730 | for edge in renderableEdges[faceIdx]: 731 | if edgeToFaceIndexMap.has(edge): 732 | 733 | if edgeToFaceIndexMap[edge].size() < 2: 734 | continue 735 | var test = edgeToFaceIndexMap[edge] 736 | 737 | if test.size()<2: 738 | continue 739 | 740 | var otherFaceIdx 741 | 742 | if test[0] == faceIdx: otherFaceIdx = test[1] 743 | elif test[1] == faceIdx: otherFaceIdx = test[0] 744 | else: 745 | continue 746 | 747 | if faceIdx == otherFaceIdx: continue 748 | var otherFace = renderables[otherFaceIdx] 749 | 750 | var cont = false 751 | if face.keys().size() == get_parent().texturesPerMesh: 752 | var otherFaceTextures = otherFace.keys() 753 | for t in otherFaceTextures: 754 | if !face.has(t): 755 | cont = true 756 | 757 | if cont == true: continue 758 | 759 | for texture in face: 760 | if(hotFaces.has(otherFaceIdx) or renderModeFaces.has(otherFaceIdx)): 761 | continue 762 | 763 | 764 | var combined =null 765 | var flag = mergeFaceFunc(faceIdx,otherFaceIdx) 766 | 767 | if flag == false: 768 | continue 769 | 770 | mergeHappened = true 771 | 772 | var otherFacesEdges = renderableEdges[otherFaceIdx].duplicate() 773 | renderableEdges[otherFaceIdx].clear() 774 | renderableEdges[faceIdx] += otherFacesEdges 775 | 776 | for e in otherFacesEdges: 777 | if !edgeToFaceIndexMap.has(e): 778 | continue 779 | if edgeToFaceIndexMap[e].size()<1: 780 | continue 781 | 782 | if edgeToFaceIndexMap[e][0] == otherFaceIdx: 783 | edgeToFaceIndexMap[e][0] = faceIdx 784 | 785 | if edgeToFaceIndexMap[e].size()<2: 786 | continue 787 | 788 | if edgeToFaceIndexMap[e][1] == otherFaceIdx: 789 | edgeToFaceIndexMap[e][1] = faceIdx 790 | 791 | edgeToFaceIndexMap.erase(edge)#edge dosen't exist anymore 792 | 793 | return 794 | 795 | 796 | func mergeFaceFunc(f1Index,f2Index,hotFaces = false): 797 | if renderables.size() < f2Index: 798 | return false 799 | 800 | var f1 = renderables[f1Index] 801 | var f2 = renderables[f2Index] 802 | var mergeCount = 0 803 | 804 | if renderableEdges[f1Index].empty() or renderableEdges[f2Index].empty(): 805 | return false 806 | 807 | var newTextureCount = 0 808 | if !hotFaces: 809 | var seenDict = {} 810 | for textureName in f2: 811 | if !f1.has(textureName) and !seenDict.has(textureName): 812 | seenDict[textureName] = true 813 | newTextureCount +=1 814 | else: 815 | newTextureCount = -INF 816 | 817 | 818 | if (f1.size() + newTextureCount) > get_parent().texturesPerMesh: 819 | return false 820 | 821 | 822 | for textureName in f2: 823 | var normals1 = getFansNormals(f1)# 824 | var normals2 = getFansNormals(f2) 825 | if normals1.size() > 3 and !hotFaces: continue 826 | if normals2.size() > 3 and !hotFaces: continue 827 | 828 | var norm2 = f2[textureName][0]["normal"] 829 | if f1.has(textureName): 830 | var norm1 = f1[textureName][0]["normal"] 831 | if norm2 == norm1 or hotFaces:#this stops the lightmap unwrap function from asserting false but not sure why 832 | #print(norm1,",",norm2) 833 | f1[textureName] += f2[textureName] 834 | f2.erase(textureName) 835 | mergeCount+=1 836 | else: 837 | if mergeCount > 0: 838 | breakpoint 839 | return false 840 | else: 841 | #if f1[f1.keys()[0]][0]["normal"] == norm2 or hotFaces: 842 | #if f1[f1.keys()[0]][0]["normal"] == norm2 or hotFaces: 843 | if normals1 == normals2 or hotFaces: 844 | f1[textureName] = f2[textureName] 845 | f2.erase(textureName) 846 | mergeCount +=1 847 | #if norm2 == norm1: 848 | # print(angle) 849 | # f1[textureName] = f2[textureName] 850 | # f2.erase(textureName) 851 | # mergeCount+=1 852 | else: 853 | if mergeCount > 0: 854 | breakpoint 855 | return false 856 | 857 | 858 | 859 | #for textureName in f2: 860 | # if f1.has(textureName): 861 | # f1[textureName] += f2[textureName] 862 | # f2.erase(textureName) 863 | # else: 864 | # f1[textureName] = f2[textureName] 865 | # f2.erase(textureName) 866 | if mergeCount == 0: 867 | return false 868 | return true 869 | 870 | 871 | 872 | func mergeBrushModelFaces3(): 873 | var first = true 874 | var faces 875 | #var test0 = get_parent().modelRenderModes 876 | for model in brushModels: 877 | if first: 878 | first = false 879 | continue 880 | 881 | var modelFaceIdxs = model["faceArr"].duplicate() 882 | if modelFaceIdxs.size() < 1: 883 | return 884 | 885 | var face1Idx = modelFaceIdxs.pop_front() 886 | var face1 = renderables[face1Idx] 887 | 888 | for faceBIdx in modelFaceIdxs: 889 | var faceB = renderables[faceBIdx] 890 | 891 | if renderModeFaces.has(faceBIdx): 892 | print("model contains render surface") 893 | continue 894 | 895 | var flag = mergeFaceFunc(face1Idx,faceBIdx,true) 896 | if flag == false: 897 | continue 898 | renderModeFaces.erase(faceBIdx) 899 | 900 | 901 | 902 | 903 | func loadTGAasImage(path): 904 | var file = File.new() 905 | file.open(path,File.READ) 906 | var buffer = file.get_buffer(file.get_len()) 907 | 908 | var image = Image.new() 909 | image.load_tga_from_buffer(buffer) 910 | 911 | file.close() 912 | return image 913 | 914 | func rotImage(image:Image,dir): 915 | var w = image.get_width() 916 | var h = image.get_height() 917 | 918 | 919 | 920 | var size = image.get_size().x * image.get_size().y 921 | var rotImage = image.duplicate() 922 | 923 | image.lock() 924 | rotImage.lock() 925 | 926 | for x in image.get_width(): 927 | for y in image.get_height(): 928 | var pix = image.get_pixel(x,y) 929 | if dir == "top": 930 | rotImage.set_pixel(y,w-1-x,pix) 931 | if dir == "bottom": 932 | rotImage.set_pixel(h-1-y,x,pix) 933 | 934 | image.unlock() 935 | rotImage.unlock() 936 | return rotImage 937 | #breakpoint 938 | 939 | func textureLights(): 940 | return 941 | var meshNodes = get_parent().faceMeshNodes 942 | 943 | var textureLightPar = Spatial.new() 944 | textureLightPar.name = "Texture Lights" 945 | get_parent().add_child(textureLightPar) 946 | var oneshotDict = {} 947 | for f in meshNodes.values(): 948 | if f == null: 949 | continue 950 | 951 | if f.has_meta("textureName"): 952 | var textureName = f.get_meta("textureName") 953 | if rads.has(textureName): 954 | 955 | var color = rads[textureName] 956 | var light = SpotLight.new() 957 | var normal = f.get_meta("normal") 958 | 959 | #light.omni_range = 125 960 | light.name = textureName 961 | light.light_color = color 962 | light.light_energy = 1.7 963 | textureLightPar.add_child(light) 964 | light.spot_range = 47 965 | light.spot_attenuation = 1.72 966 | light.spot_angle = 42 967 | light.spot_angle_attenuation = 1.2 968 | light.light_indirect_energy = 3 969 | light.translation += f.global_transform.origin 970 | 971 | 972 | light.translation -= normal*get_parent().scaleFactor*5 973 | light.set_meta("norm",normal) 974 | light.set_meta("angle",atan2(normal.z,normal.y)) 975 | 976 | 977 | var ang = acos(normal.dot(Vector3(0,0,1))) 978 | var rotAxis = normal.cross(Vector3(0,0,1)) 979 | light.rotate(rotAxis,ang) 980 | #light.rotate_x(atan2(normal.z,normal.y))#rad2deg(90)) 981 | 982 | #light.rotation_degrees.x += 90 983 | #light.shadow_enabled = true 984 | var indirectFake : OmniLight = OmniLight.new() 985 | textureLightPar.add_child(indirectFake) 986 | indirectFake.translation += f.global_transform.origin + normal*get_parent().scaleFactor*10 987 | indirectFake.omni_range = 10 988 | if !oneshotDict.has(textureName): 989 | 990 | oneshotDict[textureName] = 1 991 | 992 | 993 | func getFansNormals(fans): 994 | var normals = [] 995 | for texture in fans.keys(): 996 | for face in fans[texture]: 997 | var normal = face["normal"] 998 | if !normals.has(normal): 999 | normals.append(normal) 1000 | 1001 | return normals 1002 | 1003 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/src/mdlLoad.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Node 3 | var file 4 | var textures = [] 5 | var fileDict = {} 6 | var bones = [] 7 | var boneIndex = 0 8 | var boneMap = {} 9 | var ittCount = -1 10 | var killSwitch = false 11 | #onready var ig = get_node("../ImmediateGeometry") 12 | 13 | 14 | func mdlParse(path): 15 | file = load("res://addons/gldsrcBSP/DFile.gd").new() 16 | 17 | if !file.loadFile(path): 18 | print("file not found") 19 | return false 20 | 21 | fileDict["magic"] = file.get_String(4) 22 | fileDict["version"] = file.get_32() 23 | fileDict["name"] = file.get_String(64) 24 | fileDict["size"] = file.get_32() 25 | fileDict["eyePosition"] = getVectorXZY(file) 26 | fileDict["min"] = getVectorXZY(file) 27 | fileDict["max"] = getVectorXZY(file) 28 | fileDict["bbmin"] = getVectorXZY(file) 29 | fileDict["bbmax"] = getVectorXZY(file) 30 | fileDict["flags"] = file.get_32() 31 | fileDict["numBones"] = file.get_32() 32 | fileDict["boneIndex"] = file.get_32() 33 | fileDict["numbonecontrollers"] = file.get_32() 34 | fileDict["bonecontrollerindex"] = file.get_32() 35 | fileDict["numhitboxes"] = file.get_32() 36 | fileDict["hitboxindex"] = file.get_32() 37 | fileDict["numseq"] = file.get_32() 38 | fileDict["seqindex"] = file.get_32() 39 | fileDict["numseqgroups"] = file.get_32() 40 | fileDict["seqgroupindex"] = file.get_32() 41 | fileDict["numTextures"] = file.get_32() 42 | fileDict["textureindex"] = file.get_32() 43 | fileDict["texturedataindex"] = file.get_32() 44 | fileDict["numskinref"] = file.get_32() 45 | fileDict["numskinfamilies"] = file.get_32() 46 | fileDict["skinindex"] = file.get_32() 47 | fileDict["numbodyparts"] = file.get_32() 48 | fileDict["bodypartindex"] = file.get_32() 49 | fileDict["numattachments"] = file.get_32() 50 | fileDict["attachmentindex"] = file.get_32() 51 | fileDict["soundtable"] = file.get_32() 52 | fileDict["soundindex"] = file.get_32() 53 | fileDict["soundgroups"] = file.get_32() 54 | fileDict["soundgroupindex"] = file.get_32() 55 | fileDict["numtransitions"] = file.get_32() 56 | fileDict["transitionindex"] = file.get_32() 57 | 58 | #print("numTextures:",fileDict["numTextures"]) 59 | file.seek(fileDict["textureindex"]) 60 | for i in fileDict["numTextures"]: 61 | textures.append(parseTexture()) 62 | 63 | if fileDict["numTextures"] == 0: 64 | var searchPath = path.split(".")[0] 65 | searchPath = searchPath + "t.mdl" 66 | var fExist= File.new() 67 | var doesExist = fExist.file_exists(searchPath) 68 | fExist.close() 69 | 70 | if doesExist: 71 | var textureParse = Node.new() 72 | var script = load("res://addons/gldsrcBSP/src/mdlLoad.gd") 73 | textureParse.set_script(script) 74 | add_child(textureParse) 75 | textures = textureParse.mdlParseTextures(searchPath) 76 | 77 | 78 | parseBones() 79 | boneHier2() 80 | var seq = parseSequence() 81 | return parseBodyPart() 82 | 83 | 84 | 85 | func mdlParseTextures(path): 86 | file = load("res://addons/gldsrcBSP/DFile.gd").new() 87 | 88 | if !file.loadFile(path): 89 | print("file not found") 90 | return false 91 | 92 | fileDict["magic"] = file.get_String(4) 93 | fileDict["version"] = file.get_32() 94 | fileDict["name"] = file.get_String(64) 95 | fileDict["size"] = file.get_32() 96 | fileDict["eyePosition"] = getVectorXZY(file) 97 | fileDict["min"] = getVectorXZY(file) 98 | fileDict["max"] = getVectorXZY(file) 99 | fileDict["bbmin"] = getVectorXZY(file) 100 | fileDict["bbmax"] = getVectorXZY(file) 101 | fileDict["flags"] = file.get_32() 102 | fileDict["numBones"] = file.get_32() 103 | fileDict["boneIndex"] = file.get_32() 104 | fileDict["numbonecontrollers"] = file.get_32() 105 | fileDict["bonecontrollerindex"] = file.get_32() 106 | fileDict["numhitboxes"] = file.get_32() 107 | fileDict["hitboxindex"] = file.get_32() 108 | fileDict["numseq"] = file.get_32() 109 | fileDict["seqindex"] = file.get_32() 110 | fileDict["numseqgroups"] = file.get_32() 111 | fileDict["seqgroupindex"] = file.get_32() 112 | fileDict["numTextures"] = file.get_32() 113 | fileDict["textureindex"] = file.get_32() 114 | fileDict["texturedataindex"] = file.get_32() 115 | 116 | file.seek(fileDict["textureindex"]) 117 | for i in fileDict["numTextures"]: 118 | textures.append(parseTexture()) 119 | 120 | return textures 121 | 122 | func saveScene(): 123 | var i = 0 124 | for c in get_children(): 125 | c.set_owner(self) 126 | # var packed_scene = PackedScene.new() 127 | # packed_scene.pack(c) 128 | # ResourceSaver.save(String(i) + ".tscn", packed_scene) 129 | # i+= 1 130 | 131 | 132 | var packed_scene = PackedScene.new() 133 | packed_scene.pack(self) 134 | ResourceSaver.save(String(i) + ".tscn", packed_scene) 135 | # i+= 1 136 | print("saved") 137 | 138 | 139 | func parseTexture(): 140 | var textureDict = {} 141 | #if fileDict["textureindex"] == 0 :return 142 | #file.seek(fileDict["textureindex"]) 143 | 144 | textureDict["name"] = file.get_String(64) 145 | textureDict["flags"] = file.get_32() 146 | textureDict["width"] = file.get_32() 147 | textureDict["height"] = file.get_32() 148 | textureDict["index"] = file.get_32() 149 | 150 | var w = textureDict["width"] 151 | var h = textureDict["height"] 152 | var image = Image.new() 153 | image.create(w,h,false,Image.FORMAT_RGBA8) 154 | 155 | var pPos = file.get_position() 156 | 157 | file.seek(textureDict["index"]) 158 | 159 | var pallete = [] 160 | var colorArr = [] 161 | 162 | for y in h: 163 | for x in w: 164 | var colorIndex = file.get_8() 165 | colorArr.append(colorIndex) 166 | 167 | # file.get_8() 168 | 169 | for c in 256: 170 | var r = file.get_8() / 255.0 171 | var g = file.get_8() / 255.0 172 | var b = file.get_8() / 255.0 173 | 174 | pallete.append(Color(r,g,b)) 175 | 176 | image.lock() 177 | 178 | 179 | for y in h: 180 | for x in w: 181 | var colorIndex = colorArr[x+(y*w)] 182 | var color = pallete[colorIndex] 183 | image.set_pixel(x,y,color) 184 | 185 | 186 | image.unlock() 187 | 188 | var texture = ImageTexture.new() 189 | texture.create_from_image(image) 190 | if true: 191 | texture.flags -= texture.FLAG_FILTER 192 | 193 | file.seek(pPos) 194 | return texture 195 | 196 | 197 | func parseSequence(): 198 | var sequences = [] 199 | file.seek(fileDict["seqindex"]) 200 | for i in fileDict["numseq"]: 201 | var sequenceDict = {} 202 | sequenceDict["name"] = file.get_String(32) 203 | sequenceDict["fps"] = file.get_float32() 204 | sequenceDict["flags"] = file.get_32() 205 | sequenceDict["activity"] = file.get_32() 206 | sequenceDict["actweight"] = file.get_32() 207 | sequenceDict["numevents"] = file.get_32() 208 | sequenceDict["eventindex"] = file.get_32() 209 | sequenceDict["numframes"] = file.get_32() 210 | sequenceDict["numpivots"] = file.get_32() 211 | sequenceDict["pivotIndex"] = file.get_32() 212 | sequenceDict["motionType"] = file.get_32() 213 | sequenceDict["motionBone"] = file.get_32() 214 | sequenceDict["linearMovement"] = getVectorXZY(file) 215 | sequenceDict["autoMovePosIndex"] = file.get_32() 216 | sequenceDict["autoMovoeAngleIndex"] = file.get_32() 217 | sequenceDict["bbMin"] = getVectorXZY(file) 218 | sequenceDict["bbMax"] = getVectorXZY(file) 219 | sequenceDict["numBlends"] = file.get_32() 220 | sequenceDict["animIndex"] = file.get_32() 221 | sequenceDict["blendType0"] = file.get_32() 222 | sequenceDict["blendType1"] = file.get_32() 223 | sequenceDict["blendStart0"] = file.get_float32() 224 | sequenceDict["blendStart1"] = file.get_float32() 225 | sequenceDict["blendEnd0"] = file.get_float32() 226 | sequenceDict["blendEnd1"] = file.get_float32() 227 | sequenceDict["blendParent"] = file.get_float32() 228 | sequenceDict["seqGroup"] = file.get_32() 229 | sequenceDict["entryMode"] = file.get_32() 230 | sequenceDict["exitNode"] = file.get_32() 231 | sequenceDict["nodeFlags"] = file.get_32() 232 | sequenceDict["nextFlags"] = file.get_32() 233 | 234 | sequences.append(sequenceDict) 235 | parseAnims(sequenceDict["animIndex"],sequenceDict["numBlends"],sequenceDict["numframes"]) 236 | 237 | return sequences 238 | 239 | func parseAnims(offset,numBlends,numFrames): 240 | file.seek(offset) 241 | 242 | var boneToOffset = [] 243 | var blendOffsets = [] 244 | 245 | 246 | var blendLength = 6 * bones.size()#a pos and rot for each bone 247 | for o in numBlends*blendLength: 248 | blendOffsets.append(file.get_16())#an offset for each value xyz rxryryx 249 | 250 | var boneAnimData = [] 251 | 252 | for boneIdx in bones.size(): 253 | for f in numFrames: 254 | var animData = [] 255 | animData.resize(numFrames) 256 | 257 | for i in numFrames: 258 | animData[i] = 0 259 | 260 | var compressedSize = file.get_8() 261 | var uncompressedSize = file.get_8() 262 | var compressedData = [] 263 | 264 | for i in compressedSize: 265 | compressedData.append(file.get_16u()) 266 | 267 | var i = 0 268 | var j = 0 269 | 270 | while(j < uncompressedSize and i < numFrames): 271 | var index = min(compressedSize-1,j) 272 | animData[i] = compressedData[index] 273 | j+=1 274 | i+=1 275 | boneAnimData.append(animData) 276 | 277 | 278 | #breakpoint 279 | 280 | #for bone in bones.size(): 281 | 282 | # var xOffset = file.get_16() 283 | # var yOffset = file.get_16() 284 | # var zOffset = file.get_16() 285 | # var xrOffset = file.get_16() 286 | # var yrOffset = file.get_16() 287 | # var zrOffset = file.get_16() 288 | # boneToOffset.append({"xOffset":xOffset,"yOffset":yOffset,"zOffset":zOffset,"xrOffset":xrOffset,"yrOffset":yrOffset,"zrOfsset":zrOffset}) 289 | 290 | # breakpoint 291 | 292 | func parseBones(): 293 | file.seek(fileDict["boneIndex"]) 294 | for b in fileDict["numBones"]: 295 | bones.append(parseBone()) 296 | 297 | func parseBone(): 298 | var boneDict = {} 299 | 300 | 301 | boneDict["name"] = file.get_String(32) 302 | boneDict["parentIndex"] = file.get_32() 303 | boneDict["unused"] = file.get_32() 304 | boneDict["x"] = file.get_32() 305 | boneDict["y"] = file.get_32() 306 | boneDict["z"] = file.get_32() 307 | boneDict["rotX"] = file.get_32() 308 | boneDict["rotY"] = file.get_32() 309 | boneDict["rotZ"] = file.get_32() 310 | boneDict["pos"] = getVectorXZY(file) 311 | boneDict["rot"] = getVectorXZY(file) 312 | boneDict["scaleP"] = getVectorXZY(file) 313 | boneDict["scaleR"] = getVectorXZY(file) 314 | boneDict["index"] = String(boneIndex) 315 | boneDict["transform"] = Transform.IDENTITY 316 | var sphere = CSGSphere.new() 317 | 318 | #boneDict["rot"] = Vector3(-boneDict["rot"].x,boneDict["rot"].z,boneDict["rot"].y) 319 | 320 | #breakpoint 321 | boneIndex += 1 322 | return boneDict 323 | 324 | 325 | 326 | func parseBodyPart(): 327 | file.seek(fileDict["bodypartindex"]) 328 | var bodyPart = {} 329 | bodyPart["name"] = file.get_String(64) 330 | bodyPart["numModels"] = file.get_32() 331 | bodyPart["base"] = file.get_32() 332 | bodyPart["modelIndex"] = file.get_32() 333 | return parseModel(bodyPart["modelIndex"]) 334 | 335 | 336 | func parseModel(offset): 337 | file.seek(offset) 338 | var modelDict = {} 339 | modelDict["name"] = file.get_String(64) 340 | modelDict["type"] = file.get_32() 341 | modelDict["boundingRadius"] = file.get_32() 342 | modelDict["numMesh"] = file.get_32() 343 | modelDict["meshindex"] = file.get_32() 344 | modelDict["numverts"] = file.get_32() 345 | modelDict["vertinfoindex"] = file.get_32() 346 | modelDict["vertIndex"] = file.get_32() 347 | modelDict["numNorms"] = file.get_32() 348 | modelDict["normInfoIndex"] = file.get_32() 349 | modelDict["normIndex"] = file.get_32() 350 | modelDict["numGroups"] = file.get_32() 351 | modelDict["groupsIndex"] = file.get_32() 352 | 353 | var verts = [] 354 | var norms = [] 355 | var boneMap = [] 356 | file.seek(modelDict["vertIndex"]) 357 | for i in range(0,modelDict["numverts"]): 358 | verts.append(getVectorXZY(file)) 359 | 360 | file.seek(modelDict["normIndex"]) 361 | for i in range(0,modelDict["numNorms"]): 362 | norms.append(getVectorXZY(file)) 363 | 364 | 365 | file.seek(modelDict["vertinfoindex"]) 366 | for i in range(0,modelDict["numverts"]): 367 | boneMap.append(file.get_8()) 368 | #print(boneMap) 369 | 370 | var meshs = [] 371 | file.seek(modelDict["meshindex"]) 372 | var runningMesh = ArrayMesh.new() 373 | 374 | for i in range(0,modelDict["numMesh"]): 375 | var meshDict = parseMesh() 376 | 377 | for poly in meshDict["triVerts"]: 378 | var v = [] 379 | var n = [] 380 | var uv = [] 381 | var tex = [] 382 | var bones = [] 383 | 384 | for vertDict in poly: 385 | v.append(verts[vertDict["vertIndex"]]) 386 | n.append(norms[vertDict["normIndex"]]) 387 | uv.append(Vector2(vertDict["s"],vertDict["t"])) 388 | bones.append(boneMap[vertDict["vertIndex"]]) 389 | var type = poly[0]["type"] 390 | # print(meshDict["skinref"]) 391 | runningMesh = createMesh(v,n,type,uv,bones,meshDict["skinref"],runningMesh) 392 | #add_child(runningMesh) 393 | #for j in v.size()/3: 394 | # print(j) 395 | # var cur = [v[j*3],v[j*3+1],v[j*3+2]] 396 | # add_child(createMesh(cur)) 397 | 398 | var meshNode = MeshInstance.new() 399 | meshNode.mesh = runningMesh 400 | meshNode.name = "hello" 401 | return meshNode 402 | func parseMesh(): 403 | var meshDict = {} 404 | 405 | meshDict["numTris"] = file.get_32() 406 | meshDict["triIndex"] = file.get_32() 407 | meshDict["skinref"] = file.get_32() 408 | meshDict["numNorms"] = file.get_32() 409 | meshDict["normIndex"] = file.get_32() 410 | meshDict["triVerts"] = [] 411 | 412 | var pPos = file.get_position() 413 | file.seek(meshDict["triIndex"]) 414 | 415 | 416 | var count = 0 417 | 418 | for i in range(0,meshDict["numTris"]):#we have 60 tringles 419 | var t = parseTrivert() 420 | if t == null: 421 | break 422 | meshDict["triVerts"].append(t) 423 | 424 | 425 | file.seek(pPos) 426 | return meshDict 427 | 428 | 429 | 430 | func parseTrivert(): 431 | 432 | var count = file.get_16u() 433 | 434 | if count == 0: 435 | return null 436 | var tris = [] 437 | for i in abs(count): 438 | var vertDict = {} 439 | vertDict["vertIndex"] = file.get_16() 440 | vertDict["normIndex"] = file.get_16() 441 | vertDict["s"] = file.get_16() 442 | vertDict["t"] = file.get_16() 443 | vertDict["type"] = sign(count) 444 | tris.append(vertDict) 445 | 446 | return tris 447 | 448 | func createMeshFromFan(vertices): 449 | 450 | var texture 451 | var surf = SurfaceTool.new() 452 | var mesh = Mesh.new() 453 | 454 | 455 | surf.begin(Mesh.PRIMITIVE_TRIANGLE_STRIP) 456 | 457 | 458 | var TL = Vector2(INF,INF) 459 | var triVerts = [] 460 | for v in vertices.size(): 461 | triVerts.append(vertices[v]) 462 | 463 | 464 | surf.add_triangle_fan(triVerts,[],[],[],[]) 465 | surf.commit(mesh) 466 | var meshNode = MeshInstance.new() 467 | meshNode.mesh = mesh 468 | 469 | return meshNode 470 | 471 | func createMesh(vertices,normals,type,uv,boneIndices,textureIndex,runningMesh=null): 472 | var test = boneMap 473 | var center = Vector3.ZERO 474 | 475 | var surf = SurfaceTool.new() 476 | #var mesh = ArrayMesh.new() 477 | #mesh = surf.commit() 478 | var mat = createMat(textureIndex) 479 | 480 | 481 | 482 | if type == 1: surf.begin((Mesh.PRIMITIVE_TRIANGLE_STRIP)) 483 | if type == -1: surf.begin((Mesh.PRIMITIVE_TRIANGLE_FAN)) 484 | 485 | surf.set_material(mat) 486 | 487 | for v in vertices.size(): 488 | #print(v) 489 | surf.add_normal(normals[v]) 490 | surf.add_uv(uv[v]) 491 | #var bonePos = boneMap[boneIndices[v]].global_transform.origin 492 | #var bonePos = boneMap[boneIndices[v]]["transform"] 493 | #var bonePos = Vector3.ZERO#bones[boneIndices[v]]["thePos"] 494 | 495 | var bonePos = bones[boneIndices[v]]["sumPos"] 496 | var boneRot = bones[boneIndices[v]]["rot"] 497 | 498 | #bonePos = bonePos.rotated(Vector3(1,0,0),boneRot.x) 499 | #bonePos = bonePos.rotated(Vector3(0,1,0),boneRot.y) 500 | #bonePos = bonePos.rotated(Vector3(0,0,1),boneRot.z) 501 | 502 | 503 | var vert = vertices[v] 504 | 505 | #vert = vert.rotated(Vector3(1,0,0),boneRot.x) 506 | #vert = vert.rotated(Vector3(0,1,0),boneRot.y) 507 | #vert = vert.rotated(Vector3(0,0,1),boneRot.z) 508 | vert = bones[boneIndices[v]]["runningTransform"].xform(vert) 509 | # var vT = [vert.x,vert.y,vert.z,1] 510 | #vT = bones[boneIndices[v]]["runningTransform"]*vT 511 | 512 | #vert += bonePos 513 | 514 | surf.add_vertex(vert) 515 | 516 | 517 | surf.commit(runningMesh) 518 | 519 | 520 | return runningMesh 521 | 522 | func createMat(textureIndex): 523 | #print(textureIndex) 524 | var mat = SpatialMaterial.new() 525 | if textures == null: 526 | return mat 527 | 528 | if textures.size() == 0: 529 | return mat 530 | 531 | var text = textures[textureIndex] 532 | mat.albedo_texture = text 533 | mat.uv1_scale.x /= text.get_width() 534 | mat.uv1_scale.y /= text.get_height() 535 | 536 | return(mat) 537 | 538 | 539 | 540 | func boneHier2(): 541 | for bone in bones:#bones arranged by index. Setting up children data 542 | var b1Index = bones.find(bone) 543 | bone["children"] = [] 544 | for b2 in bones: 545 | var b2Index = bones.find(b2) 546 | if b2["parentIndex"] == b1Index: 547 | # bone["children"].append(b2) 548 | bone["children"].append(b2Index) 549 | 550 | #var rootBone = bones[1] 551 | boneItt2(0,Transform.IDENTITY) 552 | 553 | func boneItt2(index,runningTransform): 554 | if index == 0: 555 | var boneRot = bones[index]["rot"] 556 | var bonePos = bones[index]["pos"] 557 | var scaleR = bones[index]["scaleR"] 558 | bones[index]["sumPos"] = bonePos 559 | 560 | var localTransform = Transform.IDENTITY 561 | localTransform = localTransform.translated(bonePos) 562 | localTransform.basis = localTransform.basis.rotated(Vector3(1,0,0),boneRot.x) 563 | localTransform.basis = localTransform.basis.rotated(Vector3(0,1,0),boneRot.y) 564 | localTransform.basis = localTransform.basis.rotated(Vector3(0,0,1),boneRot.z) 565 | runningTransform *= localTransform 566 | 567 | bones[index]["runningTransform"] = runningTransform 568 | 569 | for cIndex in bones[index]["children"]: 570 | var cTransform = runningTransform 571 | 572 | var pBoneRot = bones[index]["rot"] 573 | var boneRot = bones[cIndex]["rot"] 574 | var bonePos = bones[cIndex]["pos"] 575 | 576 | 577 | var localTransform = Transform.IDENTITY 578 | localTransform = localTransform.translated(bonePos) 579 | localTransform.basis = localTransform.basis.rotated(Vector3(1,0,0),boneRot.x) 580 | localTransform.basis = localTransform.basis.rotated(Vector3(0,1,0),boneRot.y) 581 | localTransform.basis = localTransform.basis.rotated(Vector3(0,0,1),boneRot.z) 582 | cTransform *= localTransform 583 | 584 | bones[cIndex]["runningTransform"] = cTransform 585 | bones[cIndex]["sumPos"] = bones[index]["sumPos"] + bonePos#bones[cIndex]["pos"] 586 | #drawLine(bones[index]["sumPos"],bones[cIndex]["sumPos"]) 587 | boneItt2(cIndex,cTransform) 588 | 589 | 590 | 591 | 592 | func getVectorXZY(file): 593 | var vec = file.get_Vector32() 594 | #return Vector3(-vec.x,vec.z,vec.y) 595 | return Vector3(vec.x,vec.y,vec.z) 596 | -------------------------------------------------------------------------------- /addons/gldsrcBSP/src/wavLoad.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Node 3 | 4 | var file 5 | var fileDict = {} 6 | 7 | func _ready(): 8 | set_meta("hidden",true) 9 | 10 | 11 | func getStreamFromWAV(path): 12 | file = load("res://addons/gldsrcBSP/DFile.gd").new() 13 | if !file.loadFile(path): 14 | return AudioStreamSample.new() 15 | 16 | fileDict["magic"] = file.get_String(4) 17 | fileDict["chunkSize"] = file.get_32() 18 | fileDict["format"] = file.get_String(4) 19 | 20 | parseFmt() 21 | file.seek(fileDict["dataChunkOffset"]) 22 | parseData() 23 | var stream = createStream() 24 | 25 | 26 | if file.eof_reached(): 27 | return stream 28 | 29 | var cueArr = [] 30 | 31 | while !file.eof_reached(): 32 | var pos = file.get_position() 33 | if (pos + 4) >= file.get_len(): 34 | break 35 | 36 | var chunkId = file.get_String(4) 37 | if chunkId == "LIST": 38 | parseList() 39 | 40 | if chunkId == "CUE ": 41 | cueArr = parseCue() 42 | break 43 | 44 | stream.loop_end = stream.data.size() 45 | 46 | if cueArr.size()>0: 47 | stream.loop_mode = AudioStreamSample.LOOP_FORWARD 48 | stream.loop_begin = cueArr[0] 49 | 50 | if cueArr.size()>1: 51 | stream.loop_end = cueArr[1] 52 | 53 | return stream 54 | 55 | 56 | func parseFmt(): 57 | fileDict["fmtId"] = file.get_32() 58 | fileDict["fmtSize"] = file.get_32() 59 | fileDict["dataChunkOffset"] = fileDict["fmtSize"] + file.get_position() 60 | fileDict["audioFormat"] = file.get_16() 61 | fileDict["numChannels"] = file.get_16() 62 | fileDict["sampleRate"] = file.get_32() 63 | fileDict["byteRate"] = file.get_32() 64 | fileDict["blocksAlign"] = file.get_16() 65 | fileDict["bitsPerSample"] = file.get_16() 66 | 67 | func parseData(): 68 | fileDict["dataId"] = file.get_String(4) 69 | fileDict["dataSize"] = file.get_32() 70 | 71 | func createStream(): 72 | var stream = AudioStreamSample.new() 73 | stream.mix_rate = fileDict["sampleRate"] 74 | if fileDict["numChannels"] > 1: 75 | stream.stereo = true 76 | 77 | if fileDict["bitsPerSample"] == 8: stream.format = AudioStreamSample.FORMAT_8_BITS 78 | if fileDict["bitsPerSample"] == 16: stream.format = AudioStreamSample.FORMAT_16_BITS 79 | 80 | var dataSize = fileDict["dataSize"] 81 | var data = [] 82 | var size = fileDict["bitsPerSample"]/8 83 | 84 | if fileDict["bitsPerSample"] == 8: 85 | for i in range(0,dataSize): 86 | data.append((file.get_8() -128)/2.0) 87 | 88 | if fileDict["bitsPerSample"] == 16: 89 | for i in range(0,dataSize): 90 | data.append(file.get_8()) 91 | 92 | if !file.eof_reached(): 93 | while(file.get_position())%4 != 0: 94 | file.get_8()#all files that had another chunk after the data chunk had a single byte of padding 95 | if file.eof_reached(): 96 | break 97 | stream.data = data 98 | return stream 99 | 100 | func parseList(): 101 | 102 | var listDict = {} 103 | listDict["dataSize"] = file.get_32() 104 | var endPos = file.get_position() + listDict["dataSize"] 105 | listDict["chunkType"] = file.get_String(4) 106 | file.seek(endPos) 107 | 108 | func parseCue(): 109 | var curDict = {} 110 | var cueOffsets = [] 111 | curDict["dataSize"] = file.get_32() 112 | curDict["numCues"] = file.get_32() 113 | 114 | for n in curDict["numCues"]: 115 | curDict["id"] = file.get_32() 116 | curDict["position"] = file.get_32() 117 | curDict["fccChunk"] = file.get_32() 118 | curDict["chunkStart"] = file.get_32() 119 | curDict["blockStart"] = file.get_32() 120 | curDict["sampleOffset"] =file.get_32() 121 | cueOffsets.append(curDict["position"]) 122 | return cueOffsets 123 | 124 | --------------------------------------------------------------------------------