Example #1
0
/*-----------------------------------------------------------------------------
    Name        : gcStartup
    Description : This initializes the game chatting system, adding its regions to the game etc.
    Inputs      :
    Outputs     :
    Return      : void
----------------------------------------------------------------------------*/
void gcStartup(void)
{
    chathistory   *dummy;

    chathistoryfont = frFontRegister(chathistoryfontname);

    listInit(&chathistorylist);
    dummy = memAlloc(sizeof(chathistory), "DummyChatThing", NonVolatile);
    dummy->messageType = GC_BUFFERSTART;
    listAddNode(&chathistorylist,&dummy->link,dummy);
    dummy = memAlloc(sizeof(chathistory), "DummyChatThing", NonVolatile);
    dummy->messageType = GC_BUFFEREND;
    listAddNode(&chathistorylist,&dummy->link,dummy);
    curPosition = &dummy->link;

    chatmutex = (void *)CreateMutex(NULL,FALSE,NULL);

    if (chatdrawregion!=NULL)
    {
        regChildInsert(chatdrawregion, ghMainRegion);
    }
    else
    {
        feScreensLoad(GC_FIBFile);
        feCallbackAddMultiple(gcCallBack);
        feDrawCallbackAddMultiple(gcDrawCallback);
        gcScreenHandle = feScreenFind("Say_Chatting_Screen");

        chatdrawatom.x      = gcScreenHandle->atoms[0].x;
        chatdrawatom.y      = gcScreenHandle->atoms[0].y;
        chatdrawatom.width  = gcScreenHandle->atoms[0].width;
        chatdrawatom.height = gcScreenHandle->atoms[0].height;
        chatdrawatom.pData = (char *)gcChatTextDraw;

        chatwidth = chatdrawatom.width;

        textentrypos.x0     = gcScreenHandle->atoms[1].x;
        textentrypos.y0     = gcScreenHandle->atoms[1].y;
        textentrypos.x1     = gcScreenHandle->atoms[1].x+gcScreenHandle->atoms[1].width;
        textentrypos.y1     = gcScreenHandle->atoms[1].y+gcScreenHandle->atoms[1].height;

        chatdrawregion = regChildAlloc(ghMainRegion, (sdword)&chatdrawatom, chatdrawatom.x, chatdrawatom.y,
                                       chatdrawatom.width, chatdrawatom.height, 0, 0);
        chatdrawatom.region = (void*)chatdrawregion;
        regDrawFunctionSet(chatdrawregion, feUserRegionDraw);

        chatdrawregion->drawstyle[0] = chatdrawatom.drawstyle[0];
        chatdrawregion->drawstyle[1] = chatdrawatom.drawstyle[1];
        chatdrawregion->atom = &chatdrawatom;
    }

    gcRunning=TRUE;
}
Example #2
0
/*-----------------------------------------------------------------------------
    Name        : pingCreate
    Description : Create a ping
    Inputs      : loc - location to create the ping at.  Ping will not move
                  owner - optional object about which to postion a ping.
                        Ping will move with the object.  May be NULL.
                  evaluate - function to evaluate the ping.
                  userDataSize - extra memory to allocate for user data, such
                        as a ship list.
                  userID - number to pass back to evaluation function.
    Outputs     : userData - pointer to extra memory as allocated with the
                    ping structure.
    Return      : Pointer to newly allocated ping structure.
----------------------------------------------------------------------------*/
ping *pingCreate(vector *loc, SpaceObj *owner, pingeval evaluate, ubyte **userData, sdword userDataSize, udword userID)
{
    ping *newPing;

    newPing = memAlloc(sizeof(ping) + userDataSize, "Ping!", Pyrophoric);

    listAddNode(&pingList, &newPing->link, newPing);
    newPing->c = colWhite;
    newPing->size = 1.0f;
    newPing->minScreenSize = 10;
    newPing->minSize = 0.0f;
    if (owner == NULL)
    {
        newPing->centre = *loc;
    }
    else
    {
        newPing->centre = owner->posinfo.position;
    }
    newPing->owner = owner;
    newPing->creationTime = universe.totaltimeelapsed;
    newPing->pingDuration = 1.0f;
    newPing->interPingPause = 0.0f;
    newPing->evaluatePeriod = PNG_TaskPeriod;
    newPing->lastEvaluateTime = universe.totaltimeelapsed;
    newPing->evaluate = evaluate;
    newPing->userDataSize = userDataSize;
    newPing->userID = userID;
    newPing->TOMask = 0;
    if (userData != NULL)
    {
        *userData = (ubyte *)(newPing + 1);
    }
    return(newPing);
}
Example #3
0
void graphLinkVertices(Graph *G, GVertex *source, GVertex *destination, int weight, Generic ExtraInfo)
{
	GEdge *a=NULL;
	NodeList *pNodo=NULL;

	a = (GEdge *)malloc(sizeof(GEdge));
	if(a)
	{
		a->source = source;
		a->destination = destination;
		a->weight = weight;
                a->ExtraInfo = ExtraInfo;

		pNodo=nodeListNew(a);
		if(pNodo)
		{
			listAddNode(source->LAdjacents, pNodo);
		}
		else
		{
			free(a);
			a = NULL;
		}
	}
}
Example #4
0
AITeamMove *aimCreateGuardCooperatingTeam(AITeam *team, bool8 wait, bool8 remove)
{
    AITeamMove *newMove = aimCreateGuardCooperatingTeamNoAdd(team, wait, remove);

    listAddNode(&(team->moves), &(newMove->listNode), newMove);

    return newMove;
}
Example #5
0
void listAddNext(List *L, NodeList *p, NodeList *newNode){
    if(!listNodeExists(L, p)) return;
    else if(p == L->last) listAddNode(L, newNode);
    else{
        newNode->next = p->next;
        p->next = newNode;
    }
}
Example #6
0
AITeamMove *aimCreateLaunch(AITeam *team, bool8 wait, bool8 remove)
{
    AITeamMove *newMove;

    newMove = aimCreateLaunchNoAdd(team, wait, remove);

    listAddNode(&(team->moves), &(newMove->listNode), newMove);

    return newMove;
}
Example #7
0
void graphAddVertex(Graph *G, GVertex *v)
{
	NodeList *pNode=NULL;
	
	pNode = nodeListNew(v);
	if(pNode)
	{
		listAddNode(G, pNode);
	}
}
Example #8
0
AITeamMove *aimCreateFormation(AITeam *team, TypeOfFormation formationtype, bool8 wait, bool8 remove)
{
    AITeamMove *newMove;

    newMove = aimCreateFormationNoAdd(team, formationtype, wait, remove);

    listAddNode(&(team->moves), &(newMove->listNode), newMove);

    return newMove;
}
Example #9
0
AITeamMove *aimCreateSpecial(AITeam *team, SelectCommand *targets,TypeOfFormation formation, TacticsType tactics, bool8 wait, bool8 remove)
{
    AITeamMove *newMove;

    newMove = aimCreateSpecialNoAdd(team, targets, formation, tactics, wait, remove);

    listAddNode(&(team->moves), &(newMove->listNode), newMove);

    return newMove;

}
Example #10
0
AITeamMove *aimCreateKamikaze(AITeam *team, SelectCommand *targets,TypeOfFormation formation, bool8 wait, bool8 remove)
{
    AITeamMove *newMove;

    newMove = aimCreateKamikazeNoAdd(team, targets, formation, wait, remove);

    listAddNode(&(team->moves), &(newMove->listNode), newMove);

    return newMove;

}
Example #11
0
AITeamMove *aimCreateFancyGetShips(AITeam *team, ShipType shiptype, sbyte num_ships, AlternativeShips *alternatives, sdword priority, bool8 wait, bool8 remove)
{
    AITeamMove *newMove;

    dbgAssert(num_ships > 0);

    newMove = aimCreateFancyGetShipsNoAdd(team, shiptype, num_ships, alternatives, priority, wait, remove);

    listAddNode(&(team->moves), &(newMove->listNode), newMove);

    return newMove;
}
Example #12
0
List *listReadFile(char *fileName, readfn readLine){
    List *L = listNew();
    FILE *F = fopen(fileName, "r");
    if (F==NULL)	
	return(NULL);
    while(!feof(F)){
        Generic g;
        g = readLine(F);
        if(!feof(F))
            listAddNode(L, nodeListNew(g));
    }
    return L;
}
Example #13
0
AITeamMove *aimCreateMoveDone(AITeam *team, bool8 wait, bool8 remove)
{
    TypeOfFormation formation = SAME_FORMATION;
    AITeamMove *newMove = (AITeamMove *)memAlloc(sizeof(AITeamMove), "movedone", 0);

    InitNewMove(newMove,MOVE_DONE,wait,remove,formation,Neutral,aimProcessMoveDone,NULL,NULL);

//    aiplayerLog((aiIndex,"Created Move Done Move"));

    listAddNode(&(team->moves), &(newMove->listNode), newMove);

    return newMove;
}
Example #14
0
long DLLCALL listAddNodes(link_list_t* list, void** data, list_node_tag_t* tag, list_node_t* after)
{
    long			i;
    list_node_t*	node=NULL;

    if(data==NULL)
        return(-1);

    for(i=0; data[i]!=NULL ; i++)
        if((node=listAddNode(list,data[i],tag==NULL ? LIST_NODE_TAG_DEFAULT : *(tag++),node==NULL ? after:node))==NULL)
            return(i);

    return(i);
}
Example #15
0
BabyCallBack *taskCallBackRegister(babyFuncCB callback, udword num,
                                   void *data, real32 callintime)
{
    BabyCallBack *baby;
    //(maybe do check of time to see if it is volatile?)
    baby = memAlloc(sizeof(BabyCallBack), "BabyCallBack", Volatile);
    baby->babyCallBackFunc = callback;
    baby->numparm = num;
    baby->dataparm = data;
    baby->timeToExecute = callintime;
    baby->timeStarted = taskTimeElapsed;
    listAddNode(&callbacks.babies, &baby->babylink,baby);
    return(baby);
}
Example #16
0
void pingLoad(void)
{
    sdword i;
    sdword num;
    ping *tping;

    num = LoadInfoNumber();

    dbgAssert(pingList.num == 0);

    for (i=0;i<num;i++)
    {
        tping = LoadAndFixAnomalyPing();
        listAddNode(&pingList, &tping->link, tping);
    }
}
Example #17
0
long DLLCALL listAddNodeList(link_list_t* list, const link_list_t* src, list_node_t* after)
{
    long			count=0;
    list_node_t*	node=NULL;
    list_node_t*	src_node;

    if(src==NULL)
        return(-1);

    for(src_node=src->first; src_node!=NULL; src_node=src_node->next, count++) {
        if((node=listAddNode(list, src_node->data, src_node->tag, node==NULL ? after:node))==NULL)
            return(count);
        node->flags = src_node->flags;
    }

    return(count);
}
void DefenseFighter_Load(Ship *ship)
{
    DefenseFighterSpec *spec = (DefenseFighterSpec *)ship->ShipSpecifics;
    sdword num;
    sdword i;
    DefenseStruct *defenseStruct;

    num = LoadInfoNumber();

    listInit(&spec->DefenseList);

    for (i=0;i<num;i++)
    {
        defenseStruct = LoadDefenseStruct();
        listAddNode(&spec->DefenseList,&defenseStruct->bulletnode,defenseStruct);
    }
}
Example #19
0
void CloakGenerator_Load(Ship *ship)
{
    CloakGeneratorSpec *spec = (CloakGeneratorSpec *)ship->ShipSpecifics;
    sdword num;
    sdword i;
    CloakStruct *cloakStruct;

    num = LoadInfoNumber();

    listInit(&spec->CloakList);

    for (i=0;i<num;i++)
    {
        cloakStruct = LoadCloakStruct();
        listAddNode(&spec->CloakList,&cloakStruct->cloaknode,cloakStruct);
    }
}
Example #20
0
list_node_t* DLLCALL listAddNodeData(link_list_t* list, const void* data, size_t length, list_node_tag_t tag, list_node_t* after)
{
    list_node_t*	node;
    void*			buf;

    if((buf=malloc(length))==NULL)
        return(NULL);
    memcpy(buf,data,length);

    if((node=listAddNode(list,buf,tag,after))==NULL) {
        free(buf);
        return(NULL);
    }
    node->flags |= LINK_LIST_MALLOC;

    return(node);
}
Example #21
0
link_list_t* DLLCALL listExtract(link_list_t* dest_list, const list_node_t* node, long max)
{
    long			count;
    link_list_t*	list;

    if(node==NULL || node->list==NULL)
        return(NULL);

    if((list=listInit(dest_list, node->list->flags))==NULL)
        return(NULL);

    for(count=0; count<max && node!=NULL; node=node->next) {
        listAddNode(list, node->data, node->tag, list->last);
        count++;
    }

    return(list);
}
Example #22
0
list_node_t* DLLCALL listAddNodeString(link_list_t* list, const char* str, list_node_tag_t tag, list_node_t* after)
{
    list_node_t*	node;
    char*			buf;

    if(str==NULL)
        return(NULL);

    if((buf=strdup(str))==NULL)
        return(NULL);

    if((node=listAddNode(list,buf,tag,after))==NULL) {
        free(buf);
        return(NULL);
    }
    node->flags |= LINK_LIST_MALLOC;

    return(node);
}
Example #23
0
/*-----------------------------------------------------------------------------
    Name        : rmAssignPlayersLabToResearch
    Description : assigns a lab to a certain research item
    Inputs      : Lab number, research topic number
    Outputs     : none
    Return      : void
----------------------------------------------------------------------------*/
void rmAssignPlayersLabToResearch(Player *player, sdword labnumber, TechnologyType tech)
{
    ResearchTopic *topic;
    if ((topic=Researching(player, tech))!=NULL)
    {
        player->researchinfo.researchlabs[labnumber].labstatus = LS_RESEARCHITEM;
        player->researchinfo.researchlabs[labnumber].topic = topic;
        topic->numlabsresearching++;
    }
    else
    {
        topic = (ResearchTopic *)memAlloc(sizeof(ResearchTopic),"ResearchTopic",NonVolatile);
        listAddNode(&player->researchinfo.listoftopics, &topic->link, topic);
        player->researchinfo.researchlabs[labnumber].labstatus = LS_RESEARCHITEM;
        player->researchinfo.researchlabs[labnumber].topic = topic;
        topic->numlabsresearching = 1;
        topic->techresearch       = tech;
        topic->timeleft           = (real32)player->researchinfo.techstat->TimeToComplete[tech];
    }

    if ((player == universe.curPlayerPtr)&&(rmGUIActive)) rmUpdateTechList();
}
Example #24
0
void CloakGeneratorAddObj(Ship *ship,  SpaceObj *objtoadd)
{                       //Adds shiptoadd to 'ship's cloaklist
    CloakGeneratorSpec *spec = (CloakGeneratorSpec *)ship->ShipSpecifics;
    CloakStruct *newcloakstruct;

    if (bitTest(objtoadd->flags,SOF_Cloaked) || bitTest(objtoadd->flags, SOF_Cloaking) || bitTest(objtoadd->flags, SOF_DeCloaking))
    {               //if object is cloaked, don't add it...don't even think about it.
        return;
    }

    newcloakstruct = memAlloc(sizeof(CloakStruct),"CloakStruct",0);

    newcloakstruct->CloakStatus = 0.0f;
    newcloakstruct->spaceobj = objtoadd;
    listAddNode(&spec->CloakList,&newcloakstruct->cloaknode,newcloakstruct);

    //temporary...later make 'cloaking'
    bitSet(objtoadd->flags, SOF_Cloaking);
    bitSet(objtoadd->flags, SOF_CloakGenField);  //indicate object is in cloak field

    //should not have to clear the cloaked flag
    bitClear(objtoadd->flags, SOF_Cloaked);       //
    bitClear(objtoadd->flags, SOF_DeCloaking);
}
Example #25
0
/*-----------------------------------------------------------------------------
    Name        : primCreateNewCircleVerticeArray
    Description : Creates a set of vertices defining a unit circle around the axis given
    Inputs      : nSlices - the number of polygons in the unit circle,
                  axis - the axis around which the circle is drawn
    Outputs     : Allocates some memory and stuff
    Return      : the new vertice array
----------------------------------------------------------------------------*/
vertice_array *primCreateNewCircleVerticeArray(sdword nSlices, uword axis)
{
    udword i;
    double theta = 0.0;
    vertice_array *vertices = (vertice_array *)memAlloc(sizeofverticearray(nSlices+1), "circle_vertices", NonVolatile);

    vertices->num_vertices = nSlices + 1;
    vertices->axis         = axis;

    for (i = 0; i < vertices->num_vertices; i++)
    {
        switch (axis)
        {
            case X_AXIS:
                vertices->vertice[i].x = 0.0;
                vertices->vertice[i].y = (real32)(cos(theta));
                vertices->vertice[i].z = (real32)(sin(theta));
                break;
            case Y_AXIS:
                vertices->vertice[i].x = (real32)(sin(theta));
                vertices->vertice[i].y = 0.0;
                vertices->vertice[i].z = (real32)(cos(theta));
                break;
            case Z_AXIS:
                vertices->vertice[i].x = (real32)(sin(theta));
                vertices->vertice[i].y = (real32)(cos(theta));
                vertices->vertice[i].z = 0.0;
                break;
        }
        theta += 2.0 * PI / (double)nSlices;
    }

    listAddNode(&CircleList, &vertices->node, vertices);

    return vertices;
}
bool MinelayerCorvetteStaticMineDrop(Ship *ship,SpaceObjRotImpTarg *target)
{
    MinelayerCorvetteStatics *minelayercorvettestatics;
    MinelayerCorvetteSpec *spec = (MinelayerCorvetteSpec *)ship->ShipSpecifics;
    sdword flag;
    GunInfo *guninfo = ship->gunInfo;
    Gun *gun0,*gun1;
    real32 time;
    sdword maxmis;

    minelayercorvettestatics = (MinelayerCorvetteStatics *) ((ShipStaticInfo *)(ship->staticinfo))->custstatinfo;
    gun0 = ((Gun *) &(ship->gunInfo->guns[0]));

    maxmis = gun0->gunstatic->maxMissiles;

    if(ship->gunInfo->numGuns > 1)
    {    //ship has 2 guns (race 1)

        gun1 = ((Gun *) &(ship->gunInfo->guns[1]));

        if(gun0->numMissiles == 0 && gun1->numMissiles == 0)
            return FALSE;

        if((universe.totaltimeelapsed - gun1->lasttimefired) < minelayercorvettestatics->gunReFireTime
           && (universe.totaltimeelapsed - gun0->lasttimefired) < minelayercorvettestatics->gunReFireTime)
        {
            return(FALSE);
        }
        maxmis += gun1->gunstatic->maxMissiles;
    }
    else
    {
        if(gun0->numMissiles == 0)
            return FALSE;

        if((universe.totaltimeelapsed - gun0->lasttimefired) < minelayercorvettestatics->gunReFireTime)
            return(FALSE);
    }


    switch(spec->MiningStatus)
    {
    case FIRST_OFF:
        //////////////////////
        //speech event for forcedropped mines
        //event num: COMM_MLVette_ForceDrop
        //use battle chatter
        if(ship->playerowner->playerIndex == universe.curPlayerIndex)
        {
            if (battleCanChatterAtThisTime(BCE_COMM_MLVette_ForceDrop, ship))
            {
                battleChatterAttempt(SOUND_EVENT_DEFAULT, BCE_COMM_MLVette_ForceDrop, ship, SOUND_EVENT_DEFAULT);
            }
        }
        /////////////////////////

        spec->MiningStatus = FIRST_OFF2;
    case FIRST_OFF2:
        if(aitrackZeroRotationAnywhere(ship))
        {
            flag = 2;
        }

        if(aitrackZeroVelocity(ship))
        {
            if(flag == 2)
            {   //we're ready for next step
                MineFormationInfo *mineformationinfo;
                aitrackForceSteadyShip(ship);           //stop movement, stop rotation
                spec->MiningStatus = BEGIN_WALL_DROP_RIGHT;
                spec->MiningSideMax = 1;
                spec->MiningSideCount = 0;
                matGetVectFromMatrixCol1(spec->formation_up,ship->rotinfo.coordsys);
                matGetVectFromMatrixCol2(spec->formation_right,ship->rotinfo.coordsys);
                vecScalarMultiply(spec->formation_up, spec->formation_up, minelayercorvettestatics->MineSpacing);
                vecScalarMultiply(spec->formation_down, spec->formation_up, -1.0f);
                vecScalarMultiply(spec->formation_right,spec->formation_right,minelayercorvettestatics->MineSpacing);
                vecScalarMultiply(spec->formation_left,spec->formation_right,-1.0f);
                matGetVectFromMatrixCol3(spec->formation_heading,ship->rotinfo.coordsys);
                vecScalarMultiply(spec->formation_heading,spec->formation_heading,-minelayercorvettestatics->MineDropDistance);

                //Create Formation Entity Here

                mineformationinfo = memAlloc(sizeof(MineFormationInfo),"MineFormationInfo",NonVolatile);
                listAddNode(&universe.MineFormationList,&(mineformationinfo->FormLink),mineformationinfo);
                listInit(&mineformationinfo->MineList);
                mineformationinfo->playerowner = ship->playerowner;
                mineformationinfo->FULL = FALSE;
                mineformationinfo->wallstate = PULSE_START;
                mineformationinfo->effect = NULL;
                spec->mineforminfo = mineformationinfo;
                time = 29.0;
                spec->mineforminfo->waittime = time;     //set wait time for each pulse

                spec->formation_number_X = 0;
                spec->formation_number_Y = 0;

                vecAdd(spec->formation_position,ship->posinfo.position,spec->formation_heading);
                spec->mineaistate = MINE_DROP_FORMATION;
                MinelayerCorvetteFire(ship,target);
                spec->MineDropNumber = 1;
            }
        }
        break;
    case BEGIN_WALL_DROP_RIGHT:
        vecAddTo(spec->formation_position,spec->formation_right);
        spec->mineaistate = MINE_DROP_FORMATION;

        MinelayerCorvetteFire(ship,target);
        spec->MineDropNumber++;
        spec->formation_number_X++;
        spec->MiningSideCount++;
        if(spec->MiningSideCount == spec->MiningSideMax)
        {
            spec->MiningSideCount = 0;
            spec->MiningStatus = BEGIN_WALL_DROP_UP;
        }
        break;
    case BEGIN_WALL_DROP_UP:
        vecAddTo(spec->formation_position,spec->formation_up);
        spec->mineaistate = MINE_DROP_FORMATION;
        MinelayerCorvetteFire(ship,target);
        spec->MineDropNumber++;
        spec->formation_number_Y++;
        spec->MiningSideCount++;
        if(spec->MiningSideCount == spec->MiningSideMax)
        {
            spec->MiningSideMax++;
            spec->MiningSideCount = 0;
            spec->MiningStatus = BEGIN_WALL_DROP_LEFT;
        }
        break;
    case BEGIN_WALL_DROP_LEFT:
        vecAddTo(spec->formation_position,spec->formation_left);
        spec->mineaistate = MINE_DROP_FORMATION;
        MinelayerCorvetteFire(ship,target);
        spec->MineDropNumber++;
        spec->formation_number_X--;
        spec->MiningSideCount++;
        if(spec->MiningSideCount == spec->MiningSideMax)
        {
            spec->MiningSideCount = 0;
            spec->MiningStatus = BEGIN_WALL_DROP_DOWN;
        }
        break;
    case BEGIN_WALL_DROP_DOWN:
        vecAddTo(spec->formation_position,spec->formation_down);
        spec->mineaistate = MINE_DROP_FORMATION;
         MinelayerCorvetteFire(ship,target);
        spec->MineDropNumber++;
        spec->formation_number_Y--;
        spec->MiningSideCount++;
        if(spec->MiningSideCount == spec->MiningSideMax)
        {
            spec->MiningSideMax++;
            spec->MiningSideCount = 0;
            spec->MiningStatus = BEGIN_WALL_DROP_RIGHT;
        }
        break;
    case DONE_WAIT:
        spec->mineaistate = MINE_DROP_ATTACK;
        return TRUE;
        break;
    }
    if(spec->MineDropNumber == minelayercorvettestatics->NumMinesInSide*minelayercorvettestatics->NumMinesInSide)
    {
        if(spec->mineforminfo != NULL)
        {
            spec->mineforminfo->FULL = TRUE;
            spec->mineforminfo = NULL;
        }
        spec->mineaistate=MINE_DROP_ATTACK;
        spec->MiningStatus = DONE_WAIT;
        spec->MineDropNumber = 0;
        return(TRUE);                               //finished Wall
    }

    return(FALSE);
}
Example #27
0
/*-----------------------------------------------------------------------------
    Name        : rmUpdateResearch
    Description : updates all research
    Inputs      : none
    Outputs     : none
    Return      : void
----------------------------------------------------------------------------*/
void rmUpdateResearch(void)
{
    sdword              index, labindex, i;
    ResearchLab        *lab;
    PlayerResearchInfo *research;
    ResearchTopic      *topic;
    Node               *walk;
    LinkedList          deletelist;
    bool                shipcanbuild[STD_LAST_SHIP];

    listInit(&deletelist);

    // search through list of players
    for (index=0; index<universe.numPlayers; index++)
    {
        research = &universe.players[index].researchinfo;

        if (research->CanDoResearch)
        {
            walk = research->listoftopics.head;

            // walk through list of topics being researched
            while (walk != NULL)
            {
                topic = (ResearchTopic *)listGetStructOfNode(walk);
                topic->timeleft -= labdec[topic->numlabsresearching];
                if (topic->timeleft < 0)
                {
                    for (i = 0; i < STD_LAST_SHIP; i++)
                    {
                        shipcanbuild[i] = rmCanBuildShip(&(universe.players[index]), i);
                    }

                    // Insert sound for technology completed
                    if (universe.players[index].race == R1)
                    {
                        speechEventFleet(STAT_F_Research_R1_Completed, topic->techresearch, index);
                    }
                    else if (universe.players[index].race == R2)
                    {
                        speechEventFleet(STAT_F_Research_R2_Completed, topic->techresearch, index);
                    }

                    topic->timeleft = 0;

                    research->HasTechnology |= TechToBit(topic->techresearch);



                    listRemoveNode(&topic->link);
                    listAddNode(&deletelist,&topic->link,topic);

                    for (labindex=0; labindex<NUM_RESEARCHLABS; labindex++)
                    {
                        lab = &research->researchlabs[labindex];
                        if (lab->topic==topic)
                        {
                            lab->labstatus = LS_NORESEARCHITEM;
                            lab->topic     = NULL;
                            if (rmGUIActive)
                                rmClearLab(labindex);
                        }
                    }

                    for (i = 0; i < STD_LAST_SHIP; i++)
                    {
                        if (shipcanbuild[i] != rmCanBuildShip(&(universe.players[index]), i))
                        {
                            speechEventFleet(STAT_F_Research_CompletedShip, i, index);
                            if (cmActive)
                            {
                                cmUpdateShipsAvailable();
                            }
                        }
                    }

                    if (singlePlayerGame && (index == 0))
                    {
                        tmTechForSale[topic->techresearch] = TM_TECH_IS_ALREADY_OWNED;
                    }

                    if (rmGUIActive)
                        rmUpdateTechList();
                }

                walk = walk->next;
            }

            listDeleteAll(&deletelist);
        }
    }
}
void defensefightertargetbullet(Ship *ship, Bullet *bullettotarget)
{
    DefenseFighterSpec *spec = (DefenseFighterSpec *)ship->ShipSpecifics;
    DefenseFighterStatics *defensefighterstatics;
    DefenseStruct *newdefensestruct;
    Bullet *laser;
    GunStatic *gunstatic;
    Gun *gun;
    ShipStaticInfo *shipstatic;
    vector positionInWorldCoordSys,tempvec;
    real32 floatDamage;
    udword intDamage;
    udword intVelocity;
    udword intLength;
    etgeffectstatic *stat;
    etglod *etgLOD;
    sdword LOD;
    Effect *newEffect;

#ifdef HW_BUILD_FOR_DEBUGGING
/*    dbgMessagef("B: %d %x %x %f %f %f %x %f %x",universe.univUpdateCounter,
                                    bullettotarget->flags,
                                    bullettotarget->owner,
                                    bullettotarget->timelived,
                                    bullettotarget->damage,
                bullettotarget->damageFull,
                bullettotarget->SpecialEffectFlag,
                bullettotarget->BulletSpeed,
                bullettotarget);
*/
#endif
    gun = &ship->gunInfo->guns[0];
    gunstatic = gun->gunstatic;
    shipstatic = (ShipStaticInfo *)ship->staticinfo;
    defensefighterstatics = (DefenseFighterStatics *) ((ShipStaticInfo *)(ship->staticinfo))->custstatinfo;

    bitSet(bullettotarget->SpecialEffectFlag, 0x0002);   //set the flag

    laser = memAlloc(sizeof(Bullet),"Bullet",0);
    memset(laser,0,sizeof(Bullet));      // for safety

    laser->objtype = OBJ_BulletType;
    laser->flags = 0;
    laser->staticinfo = NULL;
    ClearNode(laser->renderlink);
    laser->currentLOD = ship->currentLOD;
    laser->cameraDistanceSquared = ship->cameraDistanceSquared;

    laser->soundType = gunstatic->gunsoundtype;
    laser->bulletType = BULLET_Laser;
    laser->owner = ship;
    laser->gunowner = gun;
    laser->target = NULL;

    laser->bulletColor = etgBulletColor[shipstatic->shiprace][laser->soundType];

    laser->bulletmass = 0.0f; //gunstatic->bulletmass;
    laser->lengthmag = 600.0f;
    laser->damage = frandombetween(defensefighterstatics->DamageReductionLow,
                                     defensefighterstatics->DamageReductionHigh);
    laser->timelived = 0.0f;
    laser->totallifetime = 100.0f;  //laser will only live for a sec anyways...
    laser->SpecialEffectFlag = 0;
    laser->traveldist = gunstatic->bulletlength;
    laser->beamtraveldist = gunstatic->bulletlength;

    //SET_MOVING_LINEARLY(laser->posinfo.isMoving);
    //laser->posinfo.haventCalculatedDist = TRUE;
    laser->DFGFieldEntryTime = 0.0f;

    matMultiplyMatByVec(&positionInWorldCoordSys,&ship->rotinfo.coordsys,&gunstatic->position);
    vecAdd(laser->posinfo.position,positionInWorldCoordSys,ship->posinfo.position);
    vecSub(laser->lengthvec, bullettotarget->posinfo.position, laser->posinfo.position);
    // heading
    tempvec = laser->lengthvec;
    vecNormalize(&tempvec);

    //matMultiplyMatByVec(&gunheadingInWorldCoordSys, &ship->rotinfo.coordsys, &tempvec);
    //laser->bulletheading = gunheadingInWorldCoordSys;
    laser->bulletheading = tempvec;
    matCreateCoordSysFromHeading(&laser->rotinfo.coordsys,&tempvec);

    vecZeroVector(laser->posinfo.velocity);

    //Laser effect...
    floatDamage = (real32)laser->damage;
    intDamage = TreatAsUdword(floatDamage);
    intVelocity = TreatAsUdword(gunstatic->bulletspeed);
    intLength = TreatAsUdword(gunstatic->bulletlength);
    //create an effect for bullet, if applicable

    etgLOD = etgGunEventTable[shipstatic->shiprace][gunstatic->gunsoundtype][EGT_GunBullet];//get pointer to bullet effect
    //etgLOD = etgGunEventTable[0][gunstatic->gunsoundtype][EGT_GunBullet];//get pointer to bullet effect
  //in future change back to proper one above...
    if (etgLOD != NULL)
    {
        if (bullettotarget != NULL)
        {
          LOD = min(ship->currentLOD, bullettotarget->currentLOD);
        }
        else
        {
          LOD = ship->currentLOD;
        }
        if (LOD >= etgLOD->nLevels)
        {
          stat = NULL;
        }
        else
        {
          stat = etgLOD->level[LOD];
        }
    }
    else
    {
      stat = NULL;
    }
#if ETG_DISABLEABLE
    if (stat != NULL && etgBulletEffectsEnabled && etgEffectsEnabled && !etgFrequencyExceeded(stat))
#else
    if (stat != NULL && etgBulletEffectsEnabled && !etgFrequencyExceeded(stat))
#endif
    {
        laser->effect = etgEffectCreate(stat, laser, NULL, NULL, NULL, 1.0f, EAF_AllButNLips, 3, intDamage, intVelocity, intLength);
//        univAddObjToRenderListIf((SpaceObj *)laser->effect,(SpaceObj *)ship);     // add to render list if parent ship is in render list
        //do length calculations :)
        ((real32 *)laser->effect->variable)[ETG_LengthVariable] =
                    fsqrt(vecMagnitudeSquared(laser->lengthvec));
    }
    else
    {
        laser->effect = NULL;                              //play no effect for this bullet
    }

//    laser->effect = NULL;               //need for render...add later?

    laser->hitEffect = etgGunEventTable[shipstatic->shiprace][bullettotarget->gunowner->gunstatic->gunsoundtype][EGT_BulletDestroyed];//get pointer to bullet effect

    if (ship->soundevent.burstHandle < 0)
    {
        soundEventBurstFire(ship, gun);
    }

    etgLOD = etgGunEventTable[shipstatic->shiprace][gunstatic->gunsoundtype][EGT_GunFire];//get pointer to bullet effect
    if (etgLOD != NULL)
    {
        LOD = ship->currentLOD;
        if (LOD >= etgLOD->nLevels)
        {
            stat = NULL;
        }
        else
        {
            stat = etgLOD->level[LOD];
        }
    }
    else
    {
        stat = NULL;
    }

#if ETG_DISABLEABLE
    if (stat != NULL && etgEffectsEnabled && etgFireEffectsEnabled && !etgFrequencyExceeded(stat))
#else
    if (stat != NULL && etgFireEffectsEnabled && !etgFrequencyExceeded(stat))
#endif
    {                                                       //if there is a gun fire effect
        newEffect = etgEffectCreate(stat, laser, NULL, NULL, NULL, 1.0f, EAF_AllButNLips, 1, intDamage);
//        univAddObjToRenderListIf((SpaceObj *)newEffect,(SpaceObj *)ship);     // add to render list if parent ship is in render list
    }
/*
//spawn bullet hitting effect
    etgLOD = etgTractorBeamEffectTable[ship->shiprace];

    //etgLOD = etgGunEventTable[shipstatic->shiprace][gunstatic->gunsoundtype][EGT_GunFire];//get pointer to bullet effect
    if (etgLOD != NULL)
    {
        LOD = ship->currentLOD;
        if (LOD >= etgLOD->nLevels)
        {
            stat = NULL;
        }
        else
        {
            stat = etgLOD->level[LOD];
        }
    }
    else
    {
        stat = NULL;
    }

#if ETG_DISABLEABLE
    if (stat != NULL && etgEffectsEnabled)
#else
    if (stat != NULL)
#endif
    {                                                       //if there is a gun fire effect
//        size = etgEffectSize(stat->nParticleBlocks);//compute size of effect
        size = stat->effectSize;
        newEffect = memAlloc(size, "DefenseFHittingEffect", 0);          //allocate the new effect

        newEffect->objtype = OBJ_EffectType;
        newEffect->flags = SOF_Rotatable | SOF_AttachVelocity | SOF_AttachPosition | SOF_AttachCoordsys;
        newEffect->staticinfo = (StaticInfo *)stat;
        ClearNode(newEffect->renderlink);
        newEffect->currentLOD = LOD;
        newEffect->cameraDistanceSquared = ship->cameraDistanceSquared;

        newEffect->timeElapsed = 0.0f;                          //brand new heavies

        floatDamage = 30.0f;
        intDamage = TreatAsUdword(floatDamage);

        newEffect->rotinfo.coordsys = bullettotarget->rotinfo.coordsys;
        newEffect->posinfo.position = bullettotarget->posinfo.position; //start at same spot as bullet
        newEffect->posinfo.velocity = bullettotarget->posinfo.velocity; //start at same spot as bullet
        etgEffectCodeStart(stat, newEffect, 1, intDamage);//get the code a-runnin'
        SET_MOVING_IMMOBILE(newEffect->posinfo.isMoving);
        newEffect->posinfo.haventCalculatedDist = TRUE;
        univUpdateObjRotInfo((SpaceObjRot *)newEffect);

//        newEffect->owner = NULL;                               // nothing owns this effect
        newEffect->owner = (Ship *) bullettotarget;
        listAddNode(&universe.SpaceObjList,&(newEffect->objlink),newEffect);
        univAddObjToRenderListIf((SpaceObj *)newEffect,(SpaceObj *)ship);     // add to render list if parent ship is in render list
    }
*/
    //Not sure If I need to add...

    listAddNode(&universe.SpaceObjList,&(laser->objlink),laser);
    listAddNode(&universe.BulletList,&(laser->bulletlink),laser);
    univAddObjToRenderListIf((SpaceObj *)laser,(SpaceObj *)ship);     // add to render list if parent ship is in render list

    newdefensestruct = memAlloc(sizeof(DefenseStruct),"DS(DefenseStruct)",Pyrophoric);
    newdefensestruct->bullet = bullettotarget;
    newdefensestruct->CoolDown = FALSE;
    newdefensestruct->CoolDownTime = 0.0f;
    newdefensestruct->LaserDead = FALSE;
    listAddNode(&spec->DefenseList,&newdefensestruct->bulletnode,newdefensestruct);
    newdefensestruct->laser = laser;



    if(bitTest(ship->flags,SOF_CloakGenField))
    {
        bitSet(ship->flags,SOF_DeCloaking);
        bitClear(ship->flags,SOF_Cloaked);
        bitClear(ship->flags,SOF_Cloaking);
    }
}