Attribute VB_Name = "Rut_Obj" Option Explicit Public Const NUM_OBJPROP_PREDEF = 11 ' nº de propiedades 'predefinidas' Private Const DELIM_CMP = """" Private Const SEPAR_CMP = "," ' crea un nuevo objeto con los datos que se pasan como parámetros ' devuelve True si pudo crearlo o False si no Public Function NuevoObjeto(ByVal sNombre As String, ByVal sAdjetivo As String, _ ByVal sDescCorta As String, ByVal sDescLarga As String, _ ByVal lPeso As Long, ByVal lTam As Long, ByVal iTipoContenedor As Integer, _ ByVal sContenedor As String, ByVal sPropiedades As String) As Boolean Dim i As Long, n As Long sNombre = QuitaAcentos(Trim(UCase(sNombre))) sAdjetivo = QuitaAcentos(Trim(UCase(sAdjetivo))) If Not bHayObj Then n = 0 Else n = UBound(Objetos) ' comprueba si el objeto ya existe For i = 0 To n If Objetos(i).Nombre = sNombre And Objetos(i).Adjetivo = sAdjetivo Then MsgBox "El objeto " & JuntaNombreAdj(sNombre, sAdjetivo) & " está repetido.", vbOKOnly + vbExclamation, "ERROR" NuevoObjeto = False Exit Function End If Next n = n + 1 End If ReDim Preserve Objetos(n) Objetos(n).Nombre = sNombre Objetos(n).Adjetivo = sAdjetivo Objetos(n).DescCorta = sDescCorta Objetos(n).DescLarga = sDescLarga Objetos(n).Peso = lPeso Objetos(n).Tam = lTam Objetos(n).TipoContenedor = iTipoContenedor Objetos(n).Contenedor = sContenedor Objetos(n).Propiedades = sPropiedades If HayPropUsrObj Then ReDim Objetos(n).PropUsr(UBound(ObjProp) - NUM_OBJPROP_PREDEF) Else ReDim Objetos(n).PropUsr(0) End If bHayObj = True NuevoObjeto = True End Function ' borra un objeto Public Sub BorrarObjeto(ByVal lPos As Long) Dim i As Long, n As Long If Not bHayObj Then Exit Sub End If n = UBound(Objetos) If lPos > n Then Exit Sub End If For i = lPos To n - 1 Objetos(i) = Objetos(i + 1) Next If n = 0 Then ReDim Objetos(0) bHayObj = False Else ReDim Preserve Objetos(n - 1) End If End Sub ' guarda la tabla de objetos, devuelve False si error Public Function GuardarObjetos(ByVal sFich As String) As Boolean Dim iFich As Integer Dim i As Long, j As Long On Error GoTo Error_GuardarObj2 iFich = FreeFile Open sFich For Output As #iFich ' propiedades de usuario If HayPropUsrObj Then For i = NUM_OBJPROP_PREDEF To UBound(ObjProp) Print #iFich, DELIM_CMP & CStr(ObjProp(i).Tipo) & DELIM_CMP & SEPAR_CMP & _ DELIM_CMP & ObjProp(i).Nombre & DELIM_CMP & SEPAR_CMP Next End If ' si está vacia la tabla de objetos sale, pero deja el fichero en blanco If Not bHayObj Then Close #iFich GuardarObjetos = True Exit Function End If On Error GoTo Error_GuardarObj1 For i = 0 To UBound(Objetos) Print #iFich, "*" & Objetos(i).Nombre Print #iFich, "+" & Objetos(i).Adjetivo Print #iFich, "{" & CStr(Len(Objetos(i).DescCorta)) & "}" & Objetos(i).DescCorta Print #iFich, "{" & CStr(Len(Objetos(i).DescLarga)) & "}" & Objetos(i).DescLarga Print #iFich, Objetos(i).Peso Print #iFich, Objetos(i).Tam Print #iFich, Objetos(i).TipoContenedor Print #iFich, Objetos(i).Contenedor Print #iFich, Objetos(i).Propiedades Print #iFich, "{" & CStr(Len(Objetos(i).Grafico)) & "}" & Objetos(i).Grafico Print #iFich, "{" & CStr(Len(Objetos(i).Sonido)) & "}" & Objetos(i).Sonido '''Print #iFich, "{" & CStr(Len(Objetos(i).Usuario)) & "}" & Objetos(i).Usuario ' si hay propiedades definidas por el usuario las guardamos If HayPropUsrObj Then For j = 0 To UBound(Objetos(i).PropUsr) Print #iFich, "{" & CStr(Len(Objetos(i).PropUsr(j))) & "}" & Objetos(i).PropUsr(j) Next For j = j To UBound(ObjProp) - NUM_OBJPROP_PREDEF Print #iFich, "{0}" Next End If Next Close #iFich GuardarObjetos = True Exit Function Error_GuardarObj1: Close #iFich Error_GuardarObj2: MsgBox "Error al guardar la tabla de objetos: " & Err.Description, _ vbOKOnly + vbCritical, "Error" GuardarObjetos = False End Function ' carga la tabla de objetos, devuelve False si error Public Function CargarObjetos(ByVal sFich As String) As Boolean Dim iFich As Integer Dim i As Long, n As Long Dim c As String, sTipo As String, sNombre As String On Error GoTo Error_CargarObj2 PropiedadesObjetos ReDim Objetos(0) bHayObj = False iFich = FreeFile Open sFich For Input As #iFich On Error GoTo Error_CargarObj1 ' si el fichero está vacío, sale If EOF(iFich) Then Close iFich CargarObjetos = True Exit Function End If ' propiedades de usuario Line Input #iFich, c If Left(c, 1) <> "*" Then ' si no hay propiedades predefinidas cogemos ' como índice -1 para que luego al incrementarse ' empiece en 0, en otro caso cogemos el índice ' del último elemento de la lista If ObjProp(0).Nombre = "" Then n = -1 Else n = UBound(ObjProp) End If Do While True n = n + 1 ReDim Preserve ObjProp(n) sTipo = SeparaCampo(c, 1, DELIM_CMP, SEPAR_CMP) sNombre = SeparaCampo(c, 2, DELIM_CMP, SEPAR_CMP) ObjProp(n).Tipo = CInt(sTipo) ObjProp(n).Nombre = UCase(sNombre) If EOF(iFich) Then Exit Do Else Line Input #iFich, c If Left(c, 1) = "*" Then Exit Do End If End If Loop End If ' cargamos objetos y sus propiedades n = 0 Do While Not EOF(iFich) ReDim Preserve Objetos(n) Objetos(n).Nombre = Mid(c, 2) Line Input #iFich, c Objetos(n).Adjetivo = Mid(c, 2) Objetos(n).DescCorta = LeeDescripcion(iFich) Objetos(n).DescLarga = LeeDescripcion(iFich) Line Input #iFich, c Objetos(n).Peso = CLng(c) Line Input #iFich, c Objetos(n).Tam = CLng(c) Line Input #iFich, c Objetos(n).TipoContenedor = CInt(c) Line Input #iFich, c Objetos(n).Contenedor = c Line Input #iFich, c Objetos(n).Propiedades = c Objetos(n).Grafico = LeeDescripcion(iFich) Objetos(n).Sonido = LeeDescripcion(iFich) '''Objetos(n).Usuario = LeeDescripcion(iFich) ' si hay propiedades definidas por el usuario las cargamos If HayPropUsrObj Then ReDim Objetos(n).PropUsr(UBound(ObjProp) - NUM_OBJPROP_PREDEF) For i = 0 To UBound(Objetos(n).PropUsr) Objetos(n).PropUsr(i) = LeeDescripcion(iFich) Next Else ReDim Objetos(n).PropUsr(0) End If n = n + 1 If Not EOF(iFich) Then Line Input #iFich, c End If Loop Close #iFich If n > 0 Then bHayObj = True End If CargarObjetos = True Exit Function Error_CargarObj1: Close #iFich Error_CargarObj2: ReDim Objetos(0) bHayObj = False MsgBox "Error al cargar la tabla de objetos: " & Err.Description, _ vbOKOnly + vbCritical, "Error" CargarObjetos = False End Function ' busca el objeto especificado y devuelve el índice del mismo ' o -1 si no lo encontró Public Function BuscaObjeto(ByVal sObjeto As String) As Long Dim i As Long Dim sNombre As String, sAdj As String sObjeto = UCase(sObjeto) SeparaNombreAdj sObjeto, sNombre, sAdj For i = 0 To UBound(Objetos) If Objetos(i).Nombre = sNombre And Objetos(i).Adjetivo = sAdj Then BuscaObjeto = i Exit Function End If Next BuscaObjeto = -1 End Function ' rellena la tabla de propiedades de los objetos Public Sub PropiedadesObjetos() If NUM_OBJPROP_PREDEF > 0 Then ReDim ObjProp(NUM_OBJPROP_PREDEF - 1) ObjProp(0).Nombre = OBJ_PROP_FEMENINO ObjProp(0).Tipo = TIPO_PROP_SINO ObjProp(1).Nombre = OBJ_PROP_PLURAL ObjProp(1).Tipo = TIPO_PROP_SINO ObjProp(2).Nombre = OBJ_PROP_ESCONTENEDOR ObjProp(2).Tipo = TIPO_PROP_SINO ObjProp(3).Nombre = OBJ_PROP_LUZ ObjProp(3).Tipo = TIPO_PROP_SINO ObjProp(4).Nombre = OBJ_PROP_INVISIBLE ObjProp(4).Tipo = TIPO_PROP_SINO ObjProp(5).Nombre = OBJ_PROP_TAPA ObjProp(5).Tipo = TIPO_PROP_SINO ObjProp(6).Nombre = OBJ_PROP_ABIERTO ObjProp(6).Tipo = TIPO_PROP_SINO ObjProp(7).Nombre = OBJ_PROP_PRENDA ObjProp(7).Tipo = TIPO_PROP_SINO ObjProp(8).Nombre = OBJ_PROP_PUESTO ObjProp(8).Tipo = TIPO_PROP_SINO ObjProp(9).Nombre = OBJ_PROP_ESCENARIO ObjProp(9).Tipo = TIPO_PROP_SINO ObjProp(10).Nombre = OBJ_PROP_ENCENDIDO ObjProp(10).Tipo = TIPO_PROP_SINO Else ReDim ObjProp(0) End If End Sub ' devuelve el valor de una propiedad de un objeto ' también ejecuta los métodos asociados a objetos ' devuelve Chr(0) si error Public Function PropiedadObj(ByVal sNombre As String, ByVal sPropiedad As String, _ ByVal sParam As String) As String Dim i As Long, lObj As Long Dim sP1 As String ' si el nombre pasado es un número accedemos al objeto por su número de orden ' si no por su nombre On Error Resume Next i = CLng(sNombre) If Err.Number = 0 Then lObj = i If Err.Number <> 0 Then PropiedadObj = Chr(0) Exit Function End If Else lObj = BuscaObjeto(sNombre) If Objetos(lObj).Nombre = "" Then PropiedadObj = Chr(0) Exit Function End If End If Err.Clear sPropiedad = UCase(sPropiedad) Select Case sPropiedad Case OBJ_PROP_NOMBRE PropiedadObj = Objetos(lObj).Nombre Case OBJ_PROP_ADJETIVO PropiedadObj = Objetos(lObj).Adjetivo Case OBJ_PROP_DESCCORTA PropiedadObj = Objetos(lObj).DescCorta Case OBJ_PROP_DESCLARGA PropiedadObj = Objetos(lObj).DescLarga Case OBJ_PROP_PESO PropiedadObj = CStr(Objetos(lObj).Peso) Case OBJ_PROP_TAM PropiedadObj = CStr(Objetos(lObj).Tam) Case OBJ_PROP_CONTENEDOR PropiedadObj = Objetos(lObj).Contenedor Case OBJ_PROP_TIPOCONTENEDOR PropiedadObj = CStr(Objetos(lObj).TipoContenedor) Case OBJ_PROP_GRAFICO PropiedadObj = Objetos(lObj).Grafico Case OBJ_PROP_SONIDO PropiedadObj = Objetos(lObj).Sonido Case OBJ_PROP_USUARIO PropiedadObj = Objetos(lObj).Usuario Case METODO_OBJETOS ' OBJ[expr].Objetos() ' devuelve un array con los objetos contenidos PropiedadObj = ObjetosContenedor(OBJ_CONTOBJ, JuntaNombreAdj(Objetos(lObj).Nombre, Objetos(lObj).Adjetivo)) Case METODO_PESOOBJETOS ' OBJ[expr].PesoObjetos() ' devuelve el peso de los objetos contenidos PropiedadObj = CStr(PesoObjetosContenedor(OBJ_CONTOBJ, JuntaNombreAdj(Objetos(lObj).Nombre, Objetos(lObj).Adjetivo))) Case METODO_METER ' OBJ[expr].Meter(obj) ' mete un objeto dentro de otro (siempre que se trate de un contenedor) sP1 = CogeParametro(sParam, 1) sP1 = AnalizaExpresion(sP1) If sP1 = Chr(0) Then PropiedadObj = Chr(0) Else PropiedadObj = IIf(PonerObjeto(lObj, OBJ_CONTOBJ, sP1), EXPR_TRUE, EXPR_FALSE) End If Case METODO_DEJAR ' OBJ[expr].Dejar(loc) ' pone el objeto en una localidad sP1 = CogeParametro(sParam, 1) sP1 = AnalizaExpresion(sP1) If sP1 = Chr(0) Then PropiedadObj = Chr(0) Else PropiedadObj = IIf(PonerObjeto(lObj, OBJ_CONTLOC, sP1), EXPR_TRUE, EXPR_FALSE) End If Case METODO_CONTIENE ' OBJ[expr].Contiene(obj) ' comprueba si el objeto contiene a otro sP1 = CogeParametro(sParam, 1) sP1 = AnalizaExpresion(sP1) If sP1 = Chr(0) Then PropiedadObj = Chr(0) Else PropiedadObj = IIf(ContieneObjeto(sP1, OBJ_CONTOBJ, lObj), EXPR_TRUE, EXPR_FALSE) End If Case Else ' propiedades definidas por el usuario For i = 0 To UBound(ObjProp) If UCase(ObjProp(i).Nombre) = sPropiedad Then If i < NUM_OBJPROP_PREDEF Then If Mid(Objetos(lObj).Propiedades, i + 1, 1) = PROP_ACTIV Then PropiedadObj = EXPR_TRUE Else PropiedadObj = EXPR_FALSE End If Else PropiedadObj = Objetos(lObj).PropUsr(i - NUM_OBJPROP_PREDEF) End If Exit Function End If Next PropiedadObj = Chr(0) End Select End Function ' asigna un valor a una propiedad de un objeto, devuelve Chr(0) si error Public Function AsignaPropiedadObj(ByVal sNombre As String, ByVal sPropiedad As String, _ ByVal sValor As String) As String Dim i As Long, lObj As Long ' si el nombre pasado es un número accedemos al objeto por su número de orden ' si no por su nombre On Error Resume Next i = CLng(sNombre) If Err.Number = 0 Then lObj = i If Err.Number <> 0 Then AsignaPropiedadObj = Chr(0) Exit Function End If Else lObj = BuscaObjeto(sNombre) If Objetos(lObj).Nombre = "" Then AsignaPropiedadObj = Chr(0) Exit Function End If End If Err.Clear sPropiedad = UCase(sPropiedad) Select Case sPropiedad Case OBJ_PROP_NOMBRE AsignaPropiedadObj = Chr(0) Exit Function Case OBJ_PROP_ADJETIVO AsignaPropiedadObj = Chr(0) Exit Function Case OBJ_PROP_DESCCORTA Objetos(lObj).DescCorta = sValor Case OBJ_PROP_DESCLARGA Objetos(lObj).DescLarga = sValor Case OBJ_PROP_PESO Objetos(lObj).Peso = CLng(sValor) If Err.Number <> 0 Then AsignaPropiedadObj = Chr(0) Exit Function End If Case OBJ_PROP_TAM Objetos(lObj).Tam = CLng(sValor) If Err.Number <> 0 Then AsignaPropiedadObj = Chr(0) Exit Function End If Case OBJ_PROP_CONTENEDOR Objetos(lObj).Contenedor = UCase(sValor) Case OBJ_PROP_TIPOCONTENEDOR Objetos(lObj).TipoContenedor = CInt(sValor) If Err.Number <> 0 Then AsignaPropiedadObj = Chr(0) Exit Function End If Case OBJ_PROP_GRAFICO Objetos(lObj).Grafico = sValor Case OBJ_PROP_SONIDO Objetos(lObj).Sonido = sValor Case OBJ_PROP_USUARIO Objetos(lObj).Usuario = sValor Case Else ' propiedades definidas por el usuario For i = 0 To UBound(ObjProp) If UCase(ObjProp(i).Nombre) = sPropiedad Then If i < NUM_OBJPROP_PREDEF Then Mid(Objetos(lObj).Propiedades, i + 1, 1) = IIf(sValor = EXPR_TRUE, PROP_ACTIV, PROP_DESACTIV) Else Objetos(lObj).PropUsr(i - NUM_OBJPROP_PREDEF) = sValor End If AsignaPropiedadObj = sValor Exit Function End If Next AsignaPropiedadObj = Chr(0) Exit Function End Select AsignaPropiedadObj = sValor End Function ' devuelve el ID de un objeto, localidad, PSI cuyo nombre y adjetivo ' coincidan con los que pasemos, además devuelve el tipo de objeto ' encontrado en la variable 'iTipo' (OBJ_OBJ, OBJ_PSI, OBJ_LOC), ' si no encuentra ninguno devuelve -1 Public Function DevuelveObjeto(ByVal sNombre As String, ByVal sAdjetivo As String, _ ByRef iTipo As Integer) As Long Dim i As Long sNombre = Trim(UCase(sNombre)) sAdjetivo = Trim(UCase(sAdjetivo)) ' buscamos primero los objetos If bHayObj Then For i = 0 To UBound(Objetos) If Objetos(i).Nombre = sNombre And Objetos(i).Adjetivo = sAdjetivo Then iTipo = OBJ_OBJ DevuelveObjeto = i Exit Function End If Next End If ' luego los PSIs If bHayPSI Then For i = 0 To UBound(PSIs) If PSIs(i).Nombre = sNombre And PSIs(i).Adjetivo = sAdjetivo Then iTipo = OBJ_PSI DevuelveObjeto = i Exit Function End If Next End If ' luego las localidades If bHayLoc Then For i = 0 To UBound(Localidades) If Localidades(i).Nombre = sNombre Then iTipo = OBJ_LOC DevuelveObjeto = i Exit Function End If Next End If iTipo = -1 DevuelveObjeto = -1 Exit Function End Function ' devuelve los objetos que hay en un contenedor (en un array), ' devuelve cadena vacía si no encontró ninguno Public Function ObjetosContenedor(ByVal iTipoCont As Integer, ByVal sCont As String) As String Dim i As Long Dim s As String If Not bHayObj Then ObjetosContenedor = "" Exit Function End If s = "" sCont = UCase(sCont) For i = 0 To UBound(Objetos) If Objetos(i).TipoContenedor = iTipoCont _ And Objetos(i).Contenedor = sCont Then s = s & JuntaNombreAdj(Objetos(i).Nombre, Objetos(i).Adjetivo) & _ Chr(SEPAR_ARRAY) End If Next ObjetosContenedor = s End Function ' devuelve el peso total de los objetos que hay en un contenedor ' devuelve 0 si no hay ninguno Public Function PesoObjetosContenedor(ByVal iTipoCont As Integer, ByVal sCont As String) As Long Dim i As Long, lPeso As Long If Not bHayObj Then PesoObjetosContenedor = 0 Exit Function End If lPeso = 0 sCont = UCase(sCont) For i = 0 To UBound(Objetos) If Objetos(i).TipoContenedor = iTipoCont _ And Objetos(i).Contenedor = sCont Then lPeso = lPeso + Objetos(i).Peso End If Next PesoObjetosContenedor = lPeso End Function ' intenta meter un objeto dentro de un contenedor (localidad, objeto, PSI) ' devuelve True Public Function PonerObjeto(ByVal lObj As Long, ByVal iTipoCont As Integer, ByVal sCont As String) As Boolean Dim lCont As Long PonerObjeto = False sCont = UCase(sCont) Select Case iTipoCont Case OBJ_CONTLOC lCont = BuscaLocalidad(sCont) If lCont >= 0 Then Objetos(lObj).TipoContenedor = OBJ_CONTLOC Objetos(lObj).Contenedor = sCont PonerObjeto = True End If Case OBJ_CONTOBJ lCont = BuscaObjeto(sCont) If lCont >= 0 Then ' comprobamos que el objeto que va a contener es un contenedor If PropiedadObj(CStr(lCont), OBJ_PROP_ESCONTENEDOR, "") = EXPR_TRUE Then Objetos(lObj).TipoContenedor = OBJ_CONTOBJ Objetos(lObj).Contenedor = sCont PonerObjeto = True End If End If Case OBJ_CONTPSI lCont = BuscaPSI(sCont) If lCont >= 0 Then Objetos(lObj).TipoContenedor = OBJ_CONTPSI Objetos(lObj).Contenedor = sCont PonerObjeto = True End If End Select End Function ' comprueba si un contenedor (localidad, objeto, PSI) contiene un objeto Public Function ContieneObjeto(ByVal sObj As String, ByVal iTipoCont As Integer, ByVal lCont As Long) As Boolean Dim lObj As Long Dim sCont As String ContieneObjeto = False lObj = BuscaObjeto(sObj) If lObj < 0 Then DescError "No se ha encontrado el objeto: " & sObj Exit Function End If Select Case iTipoCont Case OBJ_CONTLOC If Not bHayLoc Or (bHayLoc And lCont > UBound(Localidades)) Then Exit Function Else sCont = Localidades(lCont).Nombre End If Case OBJ_CONTOBJ If Not bHayObj Or (bHayObj And lCont > UBound(Objetos)) Then Exit Function Else sCont = JuntaNombreAdj(Objetos(lCont).Nombre, Objetos(lCont).Adjetivo) End If Case OBJ_CONTPSI If Not bHayPSI Or (bHayPSI And lCont > UBound(PSIs)) Then Exit Function Else sCont = JuntaNombreAdj(PSIs(lCont).Nombre, PSIs(lCont).Adjetivo) End If End Select If Objetos(lObj).TipoContenedor = iTipoCont And Objetos(lObj).Contenedor = sCont Then ContieneObjeto = True End If End Function ' devuelve True si hay propiedades de usuario definidas para los objetos Public Function HayPropUsrObj() As Boolean If UBound(ObjProp) >= NUM_OBJPROP_PREDEF And Trim(ObjProp(0).Nombre) <> "" Then HayPropUsrObj = True Else HayPropUsrObj = False End If End Function