A_FanBubbleSpawn is an action used by the Fan that, if underwater, spawns a randomly sized bubble at the actor's location. The actor randomly chooses between spawning an Object of type MT_SMALLBUBBLE, an Object of type MT_MEDIUMBUBBLE, or spawning nothing at all otherwise. Unlike the similar action A_BubbleSpawn, A_FanBubbleSpawn will never spawn MT_EXTRALARGEBUBBLE.
If the actor is not underwater when the action is called, no bubbles will be spawned by it. To save memory, bubbles are also not spawned if there is no player nearby: Var1 determines the distance in fracunits to search for players around the actor; if the actor cannot find any players within this distance, no bubbles will be spawned. This behavior is disabled if the actor has MF2_AMBUSH in its flags.
Bubble spawn chances
The exact chances of each type of bubble (or nothing) spawning are given below. Note that the result of a single P_RandomByte call (a number between 0 and 255 inclusive, stored in a variable called prandom) is used by A_FanBubbleSpawn to determine what is spawned.
// Function: A_FanBubbleSpawn//// Description: Spawns bubbles from fans, if they're underwater.//// var1 = Distance to look for players. If no player is in this distance, bubbles aren't spawned. (Ambush overrides)// var2 = unused//voidA_FanBubbleSpawn(mobj_t*actor){INT32i,locvar1=var1;UINT8prandom;mobj_t*bubble=NULL;fixed_thz=actor->z+(4*actor->height)/5;#ifdef HAVE_BLUAif(LUA_CallAction("A_FanBubbleSpawn",actor))return;#endifif(!(actor->eflags&MFE_UNDERWATER))return;if(!(actor->flags2&MF2_AMBUSH)){// Quick! Look through players!// Don't spawn bubbles unless a player is relatively close by (var2).for(i=0;i<MAXPLAYERS;++i)if(playeringame[i]&&players[i].mo&&P_AproxDistance(actor->x-players[i].mo->x,actor->y-players[i].mo->y)<(locvar1<<FRACBITS))break;// Stop looking.if(i==MAXPLAYERS)return;// don't make bubble!}prandom=P_RandomByte();if((prandom&0x7)==0x7)bubble=P_SpawnMobj(actor->x,actor->y,hz,MT_SMALLBUBBLE);elseif((prandom&0xF0)==0xF0)bubble=P_SpawnMobj(actor->x,actor->y,hz,MT_MEDIUMBUBBLE);if(bubble){bubble->destscale=actor->scale;P_SetScale(bubble,actor->scale);}}